research: preserve solver experiments and reproducible benchmarks

This commit is contained in:
Yaossg 2026-10-11 12:28:02 +08:00
parent 12e4266950
commit e93bc20b0a
85 changed files with 518443 additions and 0 deletions

View file

@ -0,0 +1,76 @@
# 普通搜索:坐标类复用及只展开有根类
2026-10-11(Asia/Hong_Kong);RTX 3060 Laptop GPU。接续 [16 候选成组筛选实验](REPORT.md)。补扫未修改、未运行。
结论:复用已接入可执行实验流程,计入分组、根生成、候选展开、必要传输、搜索和结果回传后仍有效。收益取决于同批坐标类重复率及有根类比例,不是统一倍数。对几乎无重复类的散点,直接成组筛选更快。
## 四条路径
- 模式 0:每个位置生成根,旧差过滤+区间求交。
- 模式 1:每个位置生成根,上一轮 16 候选成组筛选。
- 模式 2:坐标按 `(x mod 65536,z mod 131072)` 分类,每类生成一次根,再在 GPU 上展开任务,成组筛选。
- 模式 3:先分类、只构造代表位置;筛出类根后,仅构造和上传有根类的具体位置,再展开任务,成组筛选。
四条路径都重算本轮的类根,没有拿前一轮缓存假装免费。模式 2/3 使用各类排序后的完整根列表和位置偏移,在 GPU 上生成 `(具体位置,root)` 任务。模式 3 压缩位置后,将结果还原到原始输入索引。
程序检查根缓冲区和命中缓冲区容量,超限明确失败,不截断。单批支持最多 65,536 个位置、4,194,304 个展开后的根任务;较大任务仍需外层分批。当前是批次级调度实验,不是已经具备全世界断点续跑能力的正式扫描器。
## 实测批次耗时
预热一次、三轮轮换模式顺序。下表为 CPU 单调时钟测量的批次耗时中位数,单位 ms。
| 输入 | 位置数 / 类数 | 模式 0 | 模式 1 | 模式 2 | 模式 3 |
|---|---:|---:|---:|---:|---:|
| 已知位置所属类的全部世界内位置 | 1653 / 1 | 364.023 | 62.016 | 55.373 | 56.867 |
| 32 个有根类的全部世界内位置 | 52213 / 32 | 4691.311 | 915.446 | 656.710 | 676.742 |
| 512 个随机类,每类抽 64 个世界内位置 | 32768 / 512 | 172.222 | 141.138 | 14.235 | 9.586 |
| 4096 个均匀随机散点 | 4096 / 4096 | 24.022 | 17.902 | 19.239 | 19.502 |
**计入**:本批次位置项构造、分类、代表类筛根、类根回传/整理、偏移构造、必要 H2D 传输、GPU 根任务展开、每根公共项预计算、搜索、命中回传及排序、模式 3 结果索引还原。
**不计入**:输入文件读取、一次性 CUDA 初始化/工作区申请、专用于对照验证的完整任务回传和排序、日志打印。一次性准备另记为 `setup_ms`,这四批约 217~242 ms。预热复用了显存;新增预计算仍每轮执行。这里是长期运行时可摊薄初始化后的批次耗时,不是启动一次命令的进程总耗时。
本轮直接使用 host 时间,不与前一轮的 CUDA event 时间混算。
## 收益在哪里
以随机 512 类批次为例:
- 原先要为 32,768 个位置重复筛根;现在仅筛 512 个代表。
- 其中 19 个类有根,只有 1,216 个具体位置需要构造坐标项并传入后续搜索。
- 展开后的完整任务仍是相同的 15,424 个 `(位置,root)`,没有省略任何普通分支候选。
- 模式 3 的阶段中位数:初始分类/代表构造约 0.416 ms,类根生成约 2.049 ms,整理/展开约 0.690 ms,搜索及回传约 6.775 ms。各阶段中位数不必精确相加等于总耗时中位数。
- 相比上一轮成组筛选流程,本批再加速 14.72×;相对模式 0 为 17.97×。
32 个有根类的压力批次有 1,693,228 个根任务,全部类都必须展开,计算主要花在后续搜索。模式 3 相对模式 1 仅加速 1.35×;模式 2 略优,因为无需压缩位置和还原索引。
随机散点没有类复用收益,分类、回传和整理增加开销;模式 3 比模式 1 多耗时约 8.9%。因此应按类组织大范围遍历;不能对任意散点输入无条件启用该流程。
## 正确性和边界检查
每一轮、每一种模式均将**全部展开根任务列表**排序后与模式 0 逐项比较,并比较完整命中列表,不只是比较数量。
- 四批完整根列表和命中列表全部一致。
- 已知类批次保留原有 24 个命中,其他三批无命中。
- 全无根类的全部世界内位置:四条路径都生成 0 个任务、0 个命中;模式 3 正确处理没有具体位置可展开的情况。
- 原 21 个压力/边界位置:覆盖原点、世界边界和 int32 边界,四条路径相同的 24 个命中。
- 随机打乱 32,768 个混合位置的输入顺序:完整根和结果列表依然一致,位置压缩/还原不依赖同类位置连续排列。
原始记录在 `pipeline_results/*.jsonl`,汇总、源码哈希在 `pipeline_results/summary.json`;补充检查在 `pipeline_results/edge_validation.json`。
## 对全世界估算的影响
本轮证明此前“复用低位根”的前提可以落地,且筛类后只展开有根位置能控制部分开销。但不能把本轮 14.72× 再乘到此前约 50 天的估算上:此前约 50 天已经假定根充分复用,主要计算的是后续搜索。
本轮仅抽取 512 个随机类,根分布样本不足以重新估计全世界平均耗时;32 个有根类更是有意选择的压力集。维持此前约 50 天作为普通搜索阶段的乐观吞吐量级,不将其升级为完整全世界工期承诺。
下一步若继续研究算法,应优先减少剩余中间位组的筛选工作,或研究不同实际位置之间能否共享更高位的必要条件。当前低位根复用只消除了根生成重复,不能推导出高位结果也相同。
## 复现
```
python3 research/experiments/normal_search/run_pipeline.py
python3 research/experiments/normal_search/verify_pipeline_edges.py
```
两个脚本都会编译 GPU 基准程序。需要 NVIDIA GPU、nvcc 和 g++ 环境。实现入口为 `pipeline_bench.cu`,复用上一轮 `cuda_bench.cu` 中的内核。原正式入口未替换。

View file

@ -0,0 +1,87 @@
# 普通搜索:16 个中间位候选成组筛选
2026-10-11;RTX 3060 Laptop GPU;CUDA sm_86。仅研究普通首次输出分支,未修改或测试补扫。
结论:保留公共项预计算和 16 候选成组筛选。相对上一轮最优的“输出差过滤+区间求交”,两个独立的 65,536 随机坐标批次,搜索阶段分别加速 6.51×、6.56×。本轮代码在独立实验入口,未替换正式程序。
## 同任务实测
预热后轮换模式顺序,七轮中位数。模式 4~7 每轮重新执行 GPU 预计算,耗时已包括预计算 kernel。所有模式使用相同完整低位根列表,完整输出列表逐项比较。
| 输入 | 旧最优(模式 3) | 32 位预计算(4) | 成组筛选(7) | 3/7 |
|---|---:|---:|---:|---:|
| 已知命中位置 | 0.323584 ms | 0.268288 ms | 0.156672 ms | 2.07× |
| 21 压力/边界位置 | 1.288192 ms | 0.926720 ms | 0.223232 ms | 5.77× |
| 4096 随机位置 | 8.857600 ms | 5.859328 ms | 1.141760 ms | 7.76× |
| 65536 随机位置,原批次 | 130.136063 ms | 98.654205 ms | 19.982336 ms | 6.51× |
| 65536 随机位置,独立新批次 | 134.184967 ms | 102.582275 ms | 20.440063 ms | 6.56× |
另外测试了半差模 5(模式 5),以及半差模 5 配合角落优先检查(模式 6)。均未优于模式 7,不作为最终方案。原批次模式 5/6 分别为 114.548737/108.295166 ms。
这是搜索阶段的 CUDA event 时间,**不包括低位根生成、初始化、显存分配、排序及传输**。同次运行原批次根生成 kernel 为 267.922424 ms;若每个坐标仍单独生成根,则根生成加搜索的 kernel 时间之和从 398.058487 ms 降到 287.904760 ms,仅 1.38×。这个和是阶段计时相加,不是完整应用耗时。
此前已经验证坐标类之间可以复用低位根,但本实验没有实现全世界分组调度;不可把 6.5× 写成现有完整程序的加速倍数。
## 公共项预计算
使用归一化种子,令首格坐标项为 0。固定低 18 位 `root`,中间 17 位记为 `m`:
```
a_i = root + term_i
h_i = a_i >> 18
l_i = (a_i XOR C) & (2^18 - 1)
b_i = (A*l_i + 11) >> 17
c = C >> 18 = 0x1790d
q_i(m) = [b_i + 2*A*((m+h_i) XOR c)] mod 2^31
```
`A=0x5DEECE66D`,`C=0x5E434E432`。`h_i,b_i` 对同一个根的全部 131,072 个 m 共用,每根准备一次。最后公式按 uint32 运算取模即可,无需每个候选重复 64 位乘法。
## 为什么可以 16 个一起筛
`c=0x1790d` 的第 4~7 位为 0(最低位编号为 0)。将全部 m 唯一划分为:
```
base = (g >> 4)*256 + (g & 15), g=0..8191
m = base + 16*j, j=0..15
```
每组仅变化 m 的第 4~7 位:
- 首格 term 为 0,因此 `(m XOR c)` 随 j 线性增加,不会跨 256 边界。
- 对任意其他格,`m+h_i` 在这段长度 240 的范围内最多跨一次 256 边界。
- 同一段内,两格的输出都有相同线性增量。因此 `(q_i-q_0) mod 2^31` 是常数;整组最多两段。
- 只需计算首尾两处差值,并由进位位置求分界,即可准确判断 16 个候选哪些满足 `delta % 10 ∈ {0,8}`。
用 16 位 mask 表示一组的候选,逐格与允许 mask 求交,变成 0 就整组退出。最终剩余的具体 m 才进入原有高位区间求交及精确 Java 验证。
每根筛选线程从 131,072 个减少到 8,192 个。仍覆盖所有 m,每个线程所做的工作有所增加,因此实际收益不是理论 16×。这也没有消除中间位维度,只是利用局部等价批量处理。
## 正确性验证
- 5,000,000 次随机完整输出对照:预计算公式和原 48 位状态公式一致。
- 200,000 个随机组,约束数量循环覆盖 1~25:成组 mask 和逐个检查 16 个候选的差过滤完全一致。包括 159,120 个通过的候选,避免只对照空集。
- 已知位置全部 84 个低位根 × 8192 组,与原逐候选差过滤完全一致,共覆盖 11,010,048 个中间位候选,保留 36 个差过滤候选。
- 以上共验证 888,128 个完整组 mask。
- 五组 GPU 基准,全部模式预热与七轮测量均逐项比较完整结果列表;已知位置与压力批次保留原有 24 个命中;随机批次均无命中。
- 每批最多 64 个坐标的完整低位根列表与 CPU 对照;压力集包括世界边界、int32 边界及原点。
普通分支原有的拒绝重抽覆盖范围未改变。本实验不声称单独覆盖所有 Java 重试解。
## 全世界量级与下一步
若沿用之前的乐观假设:低位根充分复用、初始化充分摊薄,只用本次搜索阶段吞吐外推 `3,750,000²` 个锚点,则两批分别约 **49.6 天、50.8 天**,相比之前约 0.9 年有明显改善。这不是完整全世界运行时间,不含全世界分组、根缓存展开及传输,也不含补扫;不能据此承诺两个月完成。
接下来普通流程优先项:实际接上低位坐标类复用调度,计入分组、候选展开、传输的总成本。随后再研究是否能合并更多中间位组,而不是继续仅压缩高位求解的少量幸存者。
## 复现
```
python3 research/experiments/normal_search/run.py
```
需要可访问 NVIDIA GPU、nvcc、g++。脚本编译程序、运行 CPU 验证、生成独立随机坐标、顺序运行五组 GPU 基准,并写入 `results/`。不会调用补扫 kernel。
实现:`grouped.hpp`(预计算和组 mask)、`cuda_bench.cu`(基准与分组 kernel)、`cpu_verify.cpp`(独立对照)。原始七轮数据在 `results/*.jsonl`,汇总与源码哈希在 `results/summary.json`。
后续已完成计入分组、展开及传输的坐标类复用实验,见 [完整批次流程报告](PIPELINE_REPORT.md)。

View file

@ -0,0 +1,51 @@
#include "grouped.hpp"
#include <random>
#include <iostream>
#include <stdexcept>
namespace sr=slime_research;
namespace ns=normal_search;
int main(){
std::mt19937_64 rng(2026101103);
uint64_t qchecks=0,groups=0,partialSurvivors=0;
for(int test=0;test<200000;++test){
sr::CellTerm cells[25];
int32_t x=int32_t(rng()%3750000)-1875000,z=int32_t(rng()%3750000)-1875000;
const uint64_t anchor=sr::coordinateTerm(x,z);
for(int i=0;i<25;++i)cells[i]={(sr::coordinateTerm(x+i%5,z+i/5)-anchor)&sr::kMask48,sr::kSlime};
uint32_t root=rng()&((1U<<18)-1);
// Full-width random middle values also test carry and modulo behavior.
uint32_t m=rng()&((1U<<17)-1);
ns::Prepared p;ns::prepare(root,cells,p);
for(int i=0;i<25;++i){
uint32_t expected=sr::nextStateFromTerm(root+(uint64_t(m)<<18),cells[i].term)>>17;
if(ns::preparedQ(p,i,m)!=expected)throw std::runtime_error("q mismatch");
++qchecks;
}
// groupMask matches the difference filter even on odd roots; final
// solver parity checks remain responsible for discarding those roots.
int count=1+test%25;
uint32_t base=m&~240U,expected=0;
for(uint32_t j=0;j<16;++j)
if(full_search_experiment::differenceFilter(root+(uint64_t(base+16*j)<<18),cells,count))expected|=1U<<j;
partialSurvivors+=__builtin_popcount(expected);
if(ns::groupMask(p,base,count)!=expected)throw std::runtime_error("group mask mismatch");
++groups;
}
// Positive low18 roots and all middle values: check complete filter masks.
sr::CellTerm cells[25];const uint64_t anchor=sr::coordinateTerm(51069,419124);
for(int i=0;i<25;++i)cells[i]={(sr::coordinateTerm(51069+i%5,419124+i/5)-anchor)&sr::kMask48,sr::kSlime};
uint64_t accepted=0;
for(uint32_t root=0;root<(1U<<18);++root){
if(!sr::partialPatternPossible(root,18,cells,25))continue;
ns::Prepared p;ns::prepare(root,cells,p);
for(uint32_t g=0;g<8192;++g){
uint32_t base=((g>>4)<<8)+(g&15),expected=0;
for(uint32_t j=0;j<16;++j)if(full_search_experiment::differenceFilter(root+(uint64_t(base+16*j)<<18),cells,25))expected|=1U<<j;
const uint32_t actual=ns::groupMask(p,base);
if(actual!=expected)throw std::runtime_error("positive group mask mismatch");
accepted+=__builtin_popcount(actual);++groups;
}
}
if(!accepted)throw std::runtime_error("no positive candidates tested");
std::cout<<"{\"q_checks\":"<<qchecks<<",\"group_masks\":"<<groups<<",\"partial_filter_survivors\":"<<partialSurvivors<<",\"known_filter_survivors\":"<<accepted<<",\"passed\":true}\n";
}

View file

@ -0,0 +1,215 @@
#include "grouped.hpp"
#include <cuda_runtime.h>
#include <algorithm>
#include <array>
#include <chrono>
#include <cstdint>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <stdexcept>
#include <string>
#include <tuple>
#include <vector>
namespace sr = slime_research;
namespace fs = full_search_experiment;
using Clock = std::chrono::steady_clock;
#define CUDA(call) do { auto e = (call); if (e != cudaSuccess) throw std::runtime_error(std::string(#call)+": "+cudaGetErrorString(e)); } while (0)
struct Position { int32_t x, z; uint64_t anchor; sr::CellTerm cells[25]; };
struct Job { uint32_t position, root; };
struct Match { uint64_t position, seed; bool operator<(const Match& o)const{return std::tie(position,seed)<std::tie(o.position,o.seed);} bool operator==(const Match& o)const{return position==o.position&&seed==o.seed;} };
constexpr uint32_t MATCH_CAPACITY = 1U << 20;
constexpr uint32_t JOB_CAPACITY = 1U << 22;
Position makePosition(int32_t x,int32_t z) {
Position p{}; p.x=x;p.z=z;p.anchor=sr::coordinateTerm(x,z);
for(int j=0;j<5;++j)for(int i=0;i<5;++i)
p.cells[j*5+i]={(sr::coordinateTerm(x+i,z+j)-p.anchor)&sr::kMask48,sr::kSlime};
return p;
}
template<int Mode>
__global__ void rootKernel(const Position* positions,uint32_t count,const uint32_t* good,
uint32_t* counts,Job* jobs,unsigned long long* total,bool collect) {
uint64_t idx=uint64_t(blockIdx.x)*blockDim.x+threadIdx.x;
if(idx >= (uint64_t(count)<<18)) return;
const uint32_t pos=uint32_t(idx>>18), root=uint32_t(idx)&((1U<<18)-1);
const Position& p=positions[pos];
for(int i=0;i<25;++i){
const uint32_t in=root+uint32_t(p.cells[i].term);
if constexpr(Mode==0){
if((((in^uint32_t(sr::kCombinedXor))*uint32_t(sr::kJavaMultiplier)+11U)>>17)&1U)return;
}else{
const uint32_t k=in&((1U<<18)-1);
if(((good[k>>5]>>(k&31))&1U)==0)return;
}
}
atomicAdd(counts+pos,1U);
const auto at=atomicAdd(total,1ULL);
if(collect&&at<JOB_CAPACITY)jobs[at]={pos,root};
}
struct Emitter {
uint32_t position; uint64_t anchor; Match* out; unsigned long long* count;
__device__ void operator()(uint64_t s){
auto at=atomicAdd(count,1ULL);
if(at<MATCH_CAPACITY)out[at]={position,(s-anchor)&sr::kMask48};
}
};
using normal_search::Prepared;
using normal_search::preparedQ;
__global__ void prepareKernel(const Position* positions,const Job* jobs,uint32_t count,Prepared* out){
const uint32_t j=blockIdx.x*blockDim.x+threadIdx.x;
if(j<count)normal_search::prepare(jobs[j].root,positions[jobs[j].position].cells,out[j]);
}
template<int Mode>
__global__ void searchKernel(const Position* positions,const Job* jobs,uint32_t count,
Match* out,unsigned long long* total,const Prepared* prepared) {
uint64_t idx=uint64_t(blockIdx.x)*blockDim.x+threadIdx.x;
constexpr int bits=Mode==7?13:17;
if(idx >= (uint64_t(count)<<bits))return;
const Job job=jobs[idx>>bits];
const uint32_t m=idx&((1U<<bits)-1);
uint64_t low=job.root+(uint64_t(m)<<18);
const Position& p=positions[job.position];
Emitter emit{job.position,p.anchor,out,total};
if constexpr(Mode==7){
const uint32_t base=((m>>4)<<8)+(m&15);
uint32_t mask=normal_search::groupMask(prepared[idx>>13],base);
while(mask){
const uint32_t j=__ffs(mask)-1;mask &= mask-1;
const uint64_t candidate=job.root+(uint64_t(base+16*j)<<18);
fs::solveIntervals(candidate,p.cells,25,emit);
}
}
else if constexpr(Mode==3){if(fs::differenceFilter(low,p.cells,25))fs::solveIntervals(low,p.cells,25,emit);}
else {
const Prepared& t=prepared[idx>>17];
const uint32_t q0=preparedQ(t,0,m);
const uint32_t u0=(m+t.h[0])^uint32_t(sr::kCombinedXor>>18);
const int order[24]={24,4,20,12,2,10,14,22,6,8,16,18,1,3,5,9,15,19,21,23,7,11,13,17};
for(int k=1;k<25;++k){
const int i=Mode==6?order[k-1]:k;
if constexpr(Mode==4){
const uint32_t r=((preparedQ(t,i,m)-q0)&0x7fffffffU)%10;
if(r!=0&&r!=8)return;
}else{
const uint32_t ui=(m+t.h[i])^uint32_t(sr::kCombinedXor>>18);
const uint32_t d=((t.b[i]>>1)-(t.b[0]>>1)+uint32_t(sr::kJavaMultiplier)*(ui-u0))&((1U<<30)-1);
const uint32_t r=d%5;
if(r!=0&&r!=4)return;
}
}
fs::solveIntervals(low,p.cells,25,emit);
}
}
struct Device {
Prepared* prepared=nullptr; Position* positions=nullptr; Job* jobs=nullptr; Match* matches=nullptr;
uint32_t* counts=nullptr;uint32_t* good=nullptr;unsigned long long* total=nullptr;
cudaEvent_t start,stop;
Device(const std::vector<Position>& p){
CUDA(cudaMalloc(&positions,p.size()*sizeof(Position)));CUDA(cudaMemcpy(positions,p.data(),p.size()*sizeof(Position),cudaMemcpyHostToDevice));
CUDA(cudaMalloc(&jobs,JOB_CAPACITY*sizeof(Job)));CUDA(cudaMalloc(&matches,MATCH_CAPACITY*sizeof(Match)));
CUDA(cudaMalloc(&counts,p.size()*sizeof(uint32_t)));CUDA(cudaMalloc(&total,sizeof(*total)));
std::array<uint32_t,8192> bits{};
for(uint32_t k=0;k<(1U<<18);++k)if(!((((k^uint32_t(sr::kCombinedXor))*uint32_t(sr::kJavaMultiplier)+11U)>>17)&1U))bits[k>>5]|=1U<<(k&31);
CUDA(cudaMalloc(&good,sizeof(bits)));CUDA(cudaMemcpy(good,bits.data(),sizeof(bits),cudaMemcpyHostToDevice));
CUDA(cudaEventCreate(&start));CUDA(cudaEventCreate(&stop));
}
~Device(){cudaFree(prepared);cudaFree(positions);cudaFree(jobs);cudaFree(matches);cudaFree(counts);cudaFree(total);cudaFree(good);cudaEventDestroy(start);cudaEventDestroy(stop);}
float finish(){CUDA(cudaGetLastError());CUDA(cudaEventRecord(stop));CUDA(cudaEventSynchronize(stop));float ms;CUDA(cudaEventElapsedTime(&ms,start,stop));return ms;}
uint64_t totalCount(){unsigned long long n;CUDA(cudaMemcpy(&n,total,sizeof(n),cudaMemcpyDeviceToHost));return n;}
float roots(uint32_t n,int mode,bool collect){
CUDA(cudaMemset(total,0,sizeof(*total)));CUDA(cudaMemset(counts,0,n*sizeof(uint32_t)));CUDA(cudaEventRecord(start));
unsigned blocks=unsigned(((uint64_t(n)<<18)+255)/256);
if(mode==0)rootKernel<0><<<blocks,256>>>(positions,n,good,counts,jobs,total,collect);
else rootKernel<1><<<blocks,256>>>(positions,n,good,counts,jobs,total,collect);
return finish();
}
float search(uint32_t n,int mode){
if(!prepared&&n)CUDA(cudaMalloc(&prepared,n*sizeof(Prepared)));
CUDA(cudaMemset(total,0,sizeof(*total)));CUDA(cudaEventRecord(start));
unsigned blocks=unsigned(((uint64_t(n)<<17)+255)/256);
if(blocks){
if(mode>=4)prepareKernel<<<(n+127)/128,128>>>(positions,jobs,n,prepared);
if(mode==3)searchKernel<3><<<blocks,256>>>(positions,jobs,n,matches,total,prepared);
if(mode==4)searchKernel<4><<<blocks,256>>>(positions,jobs,n,matches,total,prepared);
if(mode==5)searchKernel<5><<<blocks,256>>>(positions,jobs,n,matches,total,prepared);
if(mode==6)searchKernel<6><<<blocks,256>>>(positions,jobs,n,matches,total,prepared);
if(mode==7)searchKernel<7><<<unsigned(((uint64_t(n)<<13)+255)/256),256>>>(positions,jobs,n,matches,total,prepared);
}
return finish();
}
std::vector<Match> results(){
uint64_t n=totalCount();if(n>MATCH_CAPACITY)throw std::runtime_error("match overflow");
std::vector<Match> r(n);CUDA(cudaMemcpy(r.data(),matches,n*sizeof(Match),cudaMemcpyDeviceToHost));std::sort(r.begin(),r.end());return r;
}
};
int main(int argc,char**argv){
try{
if(argc<3)throw std::runtime_error("usage: cuda_bench positions.txt normal [repeats=7]");
std::ifstream in(argv[1]);if(!in)throw std::runtime_error("cannot open positions");
int32_t x,z;std::vector<Position> positions;while(in>>x>>z)positions.push_back(makePosition(x,z));
if(positions.empty()||positions.size()>65536)throw std::runtime_error("position count must be 1..65536");
std::string task=argv[2];int repeats=argc>3?std::stoi(argv[3]):5;
if(task!="normal"||repeats<1)throw std::runtime_error("expected normal and positive repeat count");
auto processStart=Clock::now();Device d(positions);
std::cout<<std::setprecision(10);
cudaDeviceProp prop{};CUDA(cudaGetDeviceProperties(&prop,0));std::cout<<"{\"type\":\"device\",\"name\":\""<<prop.name<<"\",\"positions\":"<<positions.size()<<"}"<<std::endl;
std::vector<uint32_t> referenceCounts;
std::vector<Job> referenceJobs;
auto collectRoots=[&](int mode){
float ms=d.roots(positions.size(),mode,true);uint64_t total=d.totalCount();if(total>JOB_CAPACITY)throw std::runtime_error("job overflow");
std::vector<uint32_t> counts(positions.size());CUDA(cudaMemcpy(counts.data(),d.counts,counts.size()*sizeof(uint32_t),cudaMemcpyDeviceToHost));
std::vector<Job> jobs(total);CUDA(cudaMemcpy(jobs.data(),d.jobs,total*sizeof(Job),cudaMemcpyDeviceToHost));
std::sort(jobs.begin(),jobs.end(),[](Job a,Job b){return std::tie(a.position,a.root)<std::tie(b.position,b.root);});
if(referenceCounts.empty()){referenceCounts=counts;referenceJobs=jobs;}
else {
if(counts!=referenceCounts||jobs.size()!=referenceJobs.size())throw std::runtime_error("root mismatch");
for(size_t i=0;i<jobs.size();++i)if(jobs[i].position!=referenceJobs[i].position||jobs[i].root!=referenceJobs[i].root)throw std::runtime_error("root list mismatch");
}
return ms;
};
{
float rootMs=collectRoots(0);
CUDA(cudaMemcpy(d.jobs,referenceJobs.data(),referenceJobs.size()*sizeof(Job),cudaMemcpyHostToDevice));
std::vector<Match> expected;
const std::vector<int> modes=std::vector<int>{3,4,5,6,7};
bool first=true;
for(int m:modes){d.search(referenceJobs.size(),m);auto r=d.results();if(first){expected=r;first=false;}else if(r!=expected)throw std::runtime_error("warmup result mismatch");}
for(int r=0;r<repeats;++r)for(size_t k=0;k<modes.size();++k){
int mode=modes[(k+r)%modes.size()];auto wallStart=Clock::now();float ms=d.search(referenceJobs.size(),mode);auto result=d.results();
if(result!=expected)throw std::runtime_error("search result mismatch");
std::cout<<"{\"type\":\"search_timing\",\"mode\":"<<mode<<",\"round\":"<<r<<",\"kernel_ms\":"<<ms<<",\"scan_ms\":"<<std::chrono::duration<double,std::milli>(Clock::now()-wallStart).count()<<",\"matches\":"<<result.size()<<"}"<<std::endl;
}
std::cout<<"{\"type\":\"search_info\",\"root_ms\":"<<rootMs<<",\"jobs\":"<<referenceJobs.size()<<",\"lower35\":"<<(uint64_t(referenceJobs.size())<<17)<<",\"matches\":[";
for(size_t i=0;i<expected.size();++i){if(i)std::cout<<",";const auto& p=positions[expected[i].position];std::cout<<"["<<expected[i].seed<<","<<p.x<<","<<p.z<<"]";}std::cout<<"]}"<<std::endl;
}
// CPU checks of complete low18 root lists, including varied coordinates.
for(size_t n=0;n<std::min<size_t>(64,positions.size());++n){
size_t pos=n*positions.size()/std::min<size_t>(64,positions.size());std::vector<uint32_t> cpu,gpu;
for(uint32_t s=0;s<(1U<<18);++s)if(sr::partialPatternPossible(s,18,positions[pos].cells,25))cpu.push_back(s);
for(auto j:referenceJobs)if(j.position==pos)gpu.push_back(j.root);
if(cpu!=gpu)throw std::runtime_error("CPU/GPU roots mismatch");
}
std::map<uint64_t,std::vector<uint32_t>> classes;
size_t offset=0;
for(size_t pos=0;pos<positions.size();++pos){
uint64_t key=(uint64_t(uint32_t(positions[pos].x)&65535)<<17)|(uint32_t(positions[pos].z)&131071);
std::vector<uint32_t> roots;
while(offset<referenceJobs.size()&&referenceJobs[offset].position==pos)roots.push_back(referenceJobs[offset++].root);
auto it=classes.find(key);
if(it==classes.end())classes.emplace(key,std::move(roots));
else if(it->second!=roots)throw std::runtime_error("periodic class root list mismatch");
}
std::cout<<"{\"type\":\"periodic_validation\",\"classes\":"<<classes.size()<<",\"positions\":"<<positions.size()<<",\"equal\":true}"<<std::endl;
std::cout<<"{\"type\":\"root_counts\",\"counts\":[";for(size_t i=0;i<referenceCounts.size();++i){if(i)std::cout<<",";std::cout<<referenceCounts[i];}std::cout<<"]}"<<std::endl;
std::cout<<"{\"type\":\"process\",\"ms\":"<<std::chrono::duration<double,std::milli>(Clock::now()-processStart).count()<<"}"<<std::endl;
return 0;
}catch(const std::exception&e){std::cerr<<e.what()<<"\n";return 1;}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,42 @@
#pragma once
#include "../full_search_feasibility/interval_solver.hpp"
#if defined(__CUDACC__)
#define NS_HD __host__ __device__ __forceinline__
#else
#define NS_HD inline
#endif
namespace normal_search {
namespace sr=slime_research;
struct Prepared { uint32_t h[25], b[25]; };
NS_HD void prepare(uint32_t root,const sr::CellTerm* cells,Prepared& out){
for(int i=0;i<25;++i){
const uint64_t a=root+cells[i].term;
out.h[i]=uint32_t(a>>18);
const uint64_t lo=(a^sr::kCombinedXor)&((1U<<18)-1);
out.b[i]=uint32_t((lo*sr::kJavaMultiplier+11)>>17);
}
}
NS_HD uint32_t preparedQ(const Prepared& p,int i,uint32_t m){
const uint32_t u=(m+p.h[i])^uint32_t(sr::kCombinedXor>>18);
return (p.b[i]+2U*uint32_t(sr::kJavaMultiplier)*u)&0x7fffffffU;
}
// Bits 4..7 of kCombinedXor >> 18 are zero. For m=base+16*j,
// j in [0,16), m XOR C is affine. Each shifted input crosses at
// most one 256 boundary, so each output difference has at most two values.
// base bits 4..7 must be zero; cells[0].term must be zero (normalized anchor).
NS_HD uint32_t groupMask(const Prepared& p,uint32_t base,int count=25){
uint32_t mask=65535;
const uint32_t q0=preparedQ(p,0,base),qend=preparedQ(p,0,base+240);
for(int i=1;i<count&&mask;++i){
const uint32_t n=(256-((base+p.h[i])&255)+15)>>4;
const uint32_t before=(1U<<n)-1;
const uint32_t r0=((preparedQ(p,i,base)-q0)&0x7fffffffU)%10;
const uint32_t r1=((preparedQ(p,i,base+240)-qend)&0x7fffffffU)%10;
const uint32_t allowed=((r0==0||r0==8)?before:0U)|((r1==0||r1==8)?(65535U^before):0U);
mask &= allowed;
}
return mask;
}
}
#undef NS_HD

View file

@ -0,0 +1,114 @@
#define main component_benchmark_main
#include "cuda_bench.cu"
#undef main
__global__ void expandJobs(const uint32_t* positionClass,const uint32_t* offsets,
const uint32_t* classOffsets,const uint32_t* roots,
uint32_t n,Job* jobs){
uint32_t p=blockIdx.x*blockDim.x+threadIdx.x;
if(p>=n)return;
const uint32_t c=positionClass[p];
for(uint32_t i=classOffsets[c];i<classOffsets[c+1];++i)
jobs[offsets[p]+i-classOffsets[c]]={p,roots[i]};
}
struct Extra {
Position* reps;uint32_t *positionClass,*offsets,*classOffsets,*roots;
Extra(size_t n){
CUDA(cudaMalloc(&reps,n*sizeof(Position)));
CUDA(cudaMalloc(&positionClass,n*sizeof(uint32_t)));
CUDA(cudaMalloc(&offsets,(n+1)*sizeof(uint32_t)));
CUDA(cudaMalloc(&classOffsets,(n+1)*sizeof(uint32_t)));
CUDA(cudaMalloc(&roots,JOB_CAPACITY*sizeof(uint32_t)));
}
~Extra(){cudaFree(reps);cudaFree(positionClass);cudaFree(offsets);cudaFree(classOffsets);cudaFree(roots);}
};
struct Run {double hostMs,buildMs,rootMs,expandMs,searchMs;uint32_t classes,jobs,activePositions;std::vector<Match> matches;std::vector<Job> rootList;};
Run run(const std::vector<std::pair<int32_t,int32_t>>& coords,Device& d,Extra& extra,int mode){
const auto start=Clock::now();
auto ms=[](auto t){return std::chrono::duration<double,std::milli>(Clock::now()-t).count();};
std::vector<Position> positions;positions.reserve(coords.size());
if(mode!=3)for(auto [x,z]:coords)positions.push_back(makePosition(x,z));
std::vector<Position> reps;std::vector<uint32_t> pc;
if(mode>=2){
std::map<uint64_t,uint32_t> map;
for(auto [x,z]:coords){
uint64_t key=(uint64_t(uint32_t(x)&65535)<<17)|(uint32_t(z)&131071);
auto [it,inserted]=map.emplace(key,uint32_t(reps.size()));
if(inserted)reps.push_back(makePosition(x,z));
pc.push_back(it->second);
}
}
if(!positions.empty())CUDA(cudaMemcpy(d.positions,positions.data(),positions.size()*sizeof(Position),cudaMemcpyHostToDevice));
Run r{};r.classes=mode>=2?reps.size():positions.size();r.buildMs=ms(start);
const auto rootStart=Clock::now();
if(mode>=2){
CUDA(cudaMemcpy(extra.reps,reps.data(),reps.size()*sizeof(Position),cudaMemcpyHostToDevice));
CUDA(cudaMemset(d.total,0,sizeof(*d.total)));CUDA(cudaMemset(d.counts,0,reps.size()*sizeof(uint32_t)));
rootKernel<0><<<unsigned(((uint64_t(reps.size())<<18)+255)/256),256>>>(extra.reps,reps.size(),nullptr,d.counts,d.jobs,d.total,true);
}else d.roots(positions.size(),0,true);
uint64_t n=d.totalCount();if(n>JOB_CAPACITY)throw std::runtime_error("root capacity exceeded");
r.rootMs=ms(rootStart);
const auto expandStart=Clock::now();
std::vector<uint32_t> originalIndices;
if(mode>=2){
std::vector<Job> cj(n);if(n)CUDA(cudaMemcpy(cj.data(),d.jobs,n*sizeof(Job),cudaMemcpyDeviceToHost));
std::vector<std::vector<uint32_t>> lists(reps.size());
for(auto j:cj)lists[j.position].push_back(j.root);
if(mode==3){
std::vector<uint32_t> compactClasses;
for(uint32_t i=0;i<coords.size();++i)if(!lists[pc[i]].empty()){
auto [x,z]=coords[i];positions.push_back(makePosition(x,z));
compactClasses.push_back(pc[i]);originalIndices.push_back(i);
}
pc=std::move(compactClasses);
if(!positions.empty())CUDA(cudaMemcpy(d.positions,positions.data(),positions.size()*sizeof(Position),cudaMemcpyHostToDevice));
}
std::vector<uint32_t> roots,co{0},offsets{0};
for(auto& list:lists){std::sort(list.begin(),list.end());roots.insert(roots.end(),list.begin(),list.end());co.push_back(roots.size());}
uint64_t expanded=0;
for(auto c:pc){expanded+=lists[c].size();if(expanded>JOB_CAPACITY)throw std::runtime_error("expanded capacity exceeded; use smaller batch");offsets.push_back(expanded);}
n=expanded;
CUDA(cudaMemcpy(extra.positionClass,pc.data(),pc.size()*sizeof(uint32_t),cudaMemcpyHostToDevice));
CUDA(cudaMemcpy(extra.offsets,offsets.data(),offsets.size()*sizeof(uint32_t),cudaMemcpyHostToDevice));
CUDA(cudaMemcpy(extra.classOffsets,co.data(),co.size()*sizeof(uint32_t),cudaMemcpyHostToDevice));
if(!roots.empty())CUDA(cudaMemcpy(extra.roots,roots.data(),roots.size()*sizeof(uint32_t),cudaMemcpyHostToDevice));
if(!positions.empty())expandJobs<<<unsigned((positions.size()+255)/256),256>>>(extra.positionClass,extra.offsets,extra.classOffsets,extra.roots,positions.size(),d.jobs);
CUDA(cudaGetLastError());CUDA(cudaDeviceSynchronize());
}
r.expandMs=ms(expandStart);r.jobs=n;r.activePositions=positions.size();
const auto searchStart=Clock::now();
d.search(n,mode==0?3:7);r.matches=d.results();
if(mode==3)for(auto& match:r.matches)match.position=originalIndices[match.position];
r.searchMs=ms(searchStart);r.hostMs=ms(start);
// Validation-only transfers/sorting are outside reported pipeline time.
r.rootList.resize(n);if(n)CUDA(cudaMemcpy(r.rootList.data(),d.jobs,n*sizeof(Job),cudaMemcpyDeviceToHost));
if(mode==3)for(auto& job:r.rootList)job.position=originalIndices[job.position];
std::sort(r.rootList.begin(),r.rootList.end(),[](Job a,Job b){return std::tie(a.position,a.root)<std::tie(b.position,b.root);});
return r;
}
int main(int argc,char**argv){try{
if(argc<2)throw std::runtime_error("usage: pipeline_bench positions.txt [repeats=5]");
const auto process=Clock::now();
std::ifstream in(argv[1]);if(!in)throw std::runtime_error("cannot open input");
std::vector<std::pair<int32_t,int32_t>> coords;int32_t x,z;while(in>>x>>z)coords.emplace_back(x,z);
if(coords.empty()||coords.size()>65536)throw std::runtime_error("expected 1..65536 coordinates");
int repeats=argc>2?std::stoi(argv[2]):5;if(repeats<1)throw std::runtime_error("invalid repeats");
Device d(std::vector<Position>(coords.size()));Extra e(coords.size());
std::cout<<std::setprecision(10);
std::cout<<"{\"type\":\"setup\",\"host_ms\":"<<std::chrono::duration<double,std::milli>(Clock::now()-process).count()<<"}"<<std::endl;
Run ref;
for(int round=-1;round<repeats;++round)for(int k=0;k<4;++k){
int mode=round<0?k:(round+k)%4;
Run r=run(coords,d,e,mode);
if(round==-1&&mode==0)ref=r;
else {
if(r.matches!=ref.matches||r.rootList.size()!=ref.rootList.size())throw std::runtime_error("pipeline mismatch");
for(size_t i=0;i<r.rootList.size();++i)if(r.rootList[i].position!=ref.rootList[i].position||r.rootList[i].root!=ref.rootList[i].root)throw std::runtime_error("complete root list mismatch");
}
if(round>=0)std::cout<<"{\"type\":\"pipeline\",\"mode\":"<<mode<<",\"round\":"<<round<<",\"positions\":"<<coords.size()<<",\"classes\":"<<r.classes<<",\"active_positions\":"<<r.activePositions<<",\"jobs\":"<<r.jobs<<",\"matches\":"<<r.matches.size()<<",\"host_ms\":"<<r.hostMs<<",\"build_ms\":"<<r.buildMs<<",\"root_ms\":"<<r.rootMs<<",\"expand_ms\":"<<r.expandMs<<",\"search_ms\":"<<r.searchMs<<"}"<<std::endl;
}
std::cout<<"{\"type\":\"validation\",\"complete_roots_equal\":true,\"complete_matches_equal\":true,\"matches\":[";
for(size_t i=0;i<ref.matches.size();++i){if(i)std::cout<<",";auto m=ref.matches[i];std::cout<<"["<<m.seed<<","<<coords[m.position].first<<","<<coords[m.position].second<<"]";}
std::cout<<"]}"<<std::endl;
return 0;
}catch(const std::exception& e){std::cerr<<e.what()<<"\n";return 1;}}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,339 @@
{
"zero_lifts": {
"validation": {
"type": "validation",
"complete_roots_equal": true,
"complete_matches_equal": true,
"matches": []
},
"modes": [
{
"type": "pipeline",
"mode": 0,
"round": 0,
"positions": 1653,
"classes": 1653,
"active_positions": 1653,
"jobs": 0,
"matches": 0,
"host_ms": 5.571692,
"build_ms": 0.090188,
"root_ms": 5.379603,
"expand_ms": 0,
"search_ms": 0.101716
},
{
"type": "pipeline",
"mode": 1,
"round": 0,
"positions": 1653,
"classes": 1653,
"active_positions": 1653,
"jobs": 0,
"matches": 0,
"host_ms": 5.729661,
"build_ms": 0.1019,
"root_ms": 5.497826,
"expand_ms": 0,
"search_ms": 0.12975
},
{
"type": "pipeline",
"mode": 2,
"round": 0,
"positions": 1653,
"classes": 1,
"active_positions": 1653,
"jobs": 0,
"matches": 0,
"host_ms": 0.56059,
"build_ms": 0.10771,
"root_ms": 0.251016,
"expand_ms": 0.131594,
"search_ms": 0.070177
},
{
"type": "pipeline",
"mode": 3,
"round": 0,
"positions": 1653,
"classes": 1,
"active_positions": 0,
"jobs": 0,
"matches": 0,
"host_ms": 0.230821,
"build_ms": 0.006363,
"root_ms": 0.083272,
"expand_ms": 0.071838,
"search_ms": 0.069348
}
]
},
"stress": {
"validation": {
"type": "validation",
"complete_roots_equal": true,
"complete_matches_equal": true,
"matches": [
[
10358701894766,
51069,
419124
],
[
15959335054446,
51069,
419124
],
[
18914276748398,
51069,
419124
],
[
24514909908078,
51069,
419124
],
[
27469851602030,
51069,
419124
],
[
33070484761710,
51069,
419124
],
[
36025426455662,
51069,
419124
],
[
41626059615342,
51069,
419124
],
[
44581001309294,
51069,
419124
],
[
50181634468974,
51069,
419124
],
[
53136576162926,
51069,
419124
],
[
58737209322606,
51069,
419124
],
[
61692151016558,
51069,
419124
],
[
67292784176238,
51069,
419124
],
[
70247725870190,
51069,
419124
],
[
75848359029870,
51069,
419124
],
[
78803300723822,
51069,
419124
],
[
84403933883502,
51069,
419124
],
[
87358875577454,
51069,
419124
],
[
92959508737134,
51069,
419124
],
[
95914450431086,
51069,
419124
],
[
101515083590766,
51069,
419124
],
[
104470025284718,
51069,
419124
],
[
110070658444398,
51069,
419124
]
]
},
"modes": [
{
"type": "pipeline",
"mode": 0,
"round": 0,
"positions": 21,
"classes": 21,
"active_positions": 21,
"jobs": 474,
"matches": 24,
"host_ms": 1.476311,
"build_ms": 0.003135,
"root_ms": 0.17549,
"expand_ms": 0,
"search_ms": 1.297501
},
{
"type": "pipeline",
"mode": 1,
"round": 0,
"positions": 21,
"classes": 21,
"active_positions": 21,
"jobs": 474,
"matches": 24,
"host_ms": 0.505168,
"build_ms": 0.004611,
"root_ms": 0.175213,
"expand_ms": 9.3e-05,
"search_ms": 0.325159
},
{
"type": "pipeline",
"mode": 2,
"round": 0,
"positions": 21,
"classes": 20,
"active_positions": 21,
"jobs": 474,
"matches": 24,
"host_ms": 0.834753,
"build_ms": 0.011158,
"root_ms": 0.242071,
"expand_ms": 0.210348,
"search_ms": 0.370991
},
{
"type": "pipeline",
"mode": 3,
"round": 0,
"positions": 21,
"classes": 20,
"active_positions": 13,
"jobs": 474,
"matches": 24,
"host_ms": 0.782097,
"build_ms": 0.004335,
"root_ms": 0.1967,
"expand_ms": 0.261529,
"search_ms": 0.319533
}
]
},
"shuffled_mixed": {
"validation": {
"type": "validation",
"complete_roots_equal": true,
"complete_matches_equal": true,
"matches": []
},
"modes": [
{
"type": "pipeline",
"mode": 0,
"round": 0,
"positions": 32768,
"classes": 32768,
"active_positions": 32768,
"jobs": 15424,
"matches": 0,
"host_ms": 152.132767,
"build_ms": 4.096027,
"root_ms": 113.387564,
"expand_ms": 0.000184,
"search_ms": 34.648623
},
{
"type": "pipeline",
"mode": 1,
"round": 0,
"positions": 32768,
"classes": 32768,
"active_positions": 32768,
"jobs": 15424,
"matches": 0,
"host_ms": 124.087013,
"build_ms": 4.152926,
"root_ms": 113.998689,
"expand_ms": 0.000184,
"search_ms": 5.934844
},
{
"type": "pipeline",
"mode": 2,
"round": 0,
"positions": 32768,
"classes": 512,
"active_positions": 32768,
"jobs": 15424,
"matches": 0,
"host_ms": 13.605316,
"build_ms": 5.613835,
"root_ms": 1.992268,
"expand_ms": 0.604117,
"search_ms": 5.394911
},
{
"type": "pipeline",
"mode": 3,
"round": 0,
"positions": 32768,
"classes": 512,
"active_positions": 1216,
"jobs": 15424,
"matches": 0,
"host_ms": 9.609161,
"build_ms": 1.342779,
"root_ms": 2.238581,
"expand_ms": 0.603472,
"search_ms": 5.424052
}
]
},
"source_sha256": {
"pipeline_bench.cu": "31da815aa0ee8904c702e55d2d685282fc64bfada24dd208e151faac5c55c37c",
"cuda_bench.cu": "3e1fd6fe3bdb87ac68fe853dc4e6d2275d6aa00a692c7d630391fd12c0105c20",
"grouped.hpp": "5d48c4a45e7f7b07a362c69b5163f48d44bd45d18e7f0f02b00bda0edaadeb23",
"verify_pipeline_edges.py": "97a2b4642e871149519a79c73b7b617dd7a0cc47cd0f0dfe59cc7c8afdf0507c"
}
}

View file

@ -0,0 +1,301 @@
{
"metadata": {
"date": "2026-10-11T10:49:17.203764+08:00",
"gpu": "name, driver_version\nNVIDIA GeForce RTX 3060 Laptop GPU, 596.49\n"
},
"known_lifts": {
"0": {
"host_ms": 359.494613,
"build_ms": 0.100726,
"root_ms": 8.470989,
"expand_ms": 9.6e-05,
"search_ms": 350.821402,
"jobs": 138852,
"classes": 1653,
"positions": 1653,
"matches": 24
},
"1": {
"host_ms": 61.726379,
"build_ms": 0.127304,
"root_ms": 8.947655,
"expand_ms": 0,
"search_ms": 52.659413,
"jobs": 138852,
"classes": 1653,
"positions": 1653,
"matches": 24
},
"2": {
"host_ms": 53.625264,
"build_ms": 0.166015,
"root_ms": 0.356104,
"expand_ms": 0.319126,
"search_ms": 52.783635,
"jobs": 138852,
"classes": 1,
"positions": 1653,
"matches": 24
},
"validation": {
"type": "validation",
"complete_roots_equal": true,
"complete_matches_equal": true,
"matches": [
[
10358701894766,
51069,
419124
],
[
15959335054446,
51069,
419124
],
[
18914276748398,
51069,
419124
],
[
24514909908078,
51069,
419124
],
[
27469851602030,
51069,
419124
],
[
33070484761710,
51069,
419124
],
[
36025426455662,
51069,
419124
],
[
41626059615342,
51069,
419124
],
[
44581001309294,
51069,
419124
],
[
50181634468974,
51069,
419124
],
[
53136576162926,
51069,
419124
],
[
58737209322606,
51069,
419124
],
[
61692151016558,
51069,
419124
],
[
67292784176238,
51069,
419124
],
[
70247725870190,
51069,
419124
],
[
75848359029870,
51069,
419124
],
[
78803300723822,
51069,
419124
],
[
84403933883502,
51069,
419124
],
[
87358875577454,
51069,
419124
],
[
92959508737134,
51069,
419124
],
[
95914450431086,
51069,
419124
],
[
101515083590766,
51069,
419124
],
[
104470025284718,
51069,
419124
],
[
110070658444398,
51069,
419124
]
]
},
"setup_ms": 269.594069
},
"nonempty32": {
"0": {
"host_ms": 4621.165908,
"build_ms": 7.240293,
"root_ms": 257.582953,
"expand_ms": 0,
"search_ms": 4356.341998,
"jobs": 1693228,
"classes": 52213,
"positions": 52213,
"matches": 0
},
"1": {
"host_ms": 926.774796,
"build_ms": 7.307786,
"root_ms": 251.583683,
"expand_ms": 0,
"search_ms": 668.081633,
"jobs": 1693228,
"classes": 52213,
"positions": 52213,
"matches": 0
},
"2": {
"host_ms": 664.598058,
"build_ms": 8.052305,
"root_ms": 0.602059,
"expand_ms": 1.15488,
"search_ms": 654.776953,
"jobs": 1693228,
"classes": 32,
"positions": 52213,
"matches": 0
},
"validation": {
"type": "validation",
"complete_roots_equal": true,
"complete_matches_equal": true,
"matches": []
},
"setup_ms": 281.326323
},
"mixed512": {
"0": {
"host_ms": 170.81455,
"build_ms": 4.3475,
"root_ms": 125.510086,
"expand_ms": 0,
"search_ms": 41.628402,
"jobs": 15424,
"classes": 32768,
"positions": 32768,
"matches": 0
},
"1": {
"host_ms": 138.433459,
"build_ms": 4.575848,
"root_ms": 128.008956,
"expand_ms": 0,
"search_ms": 5.843008,
"jobs": 15424,
"classes": 32768,
"positions": 32768,
"matches": 0
},
"2": {
"host_ms": 14.418511,
"build_ms": 5.463323,
"root_ms": 2.456199,
"expand_ms": 0.614328,
"search_ms": 5.820053,
"jobs": 15424,
"classes": 512,
"positions": 32768,
"matches": 0
},
"validation": {
"type": "validation",
"complete_roots_equal": true,
"complete_matches_equal": true,
"matches": []
},
"setup_ms": 259.425362
},
"random4096": {
"0": {
"host_ms": 22.41199,
"build_ms": 0.318132,
"root_ms": 15.081804,
"expand_ms": 0,
"search_ms": 6.895335,
"jobs": 2960,
"classes": 4096,
"positions": 4096,
"matches": 0
},
"1": {
"host_ms": 16.864992,
"build_ms": 0.311931,
"root_ms": 15.251468,
"expand_ms": 0,
"search_ms": 1.256979,
"jobs": 2960,
"classes": 4096,
"positions": 4096,
"matches": 0
},
"2": {
"host_ms": 19.192994,
"build_ms": 1.265494,
"root_ms": 15.992881,
"expand_ms": 0.767331,
"search_ms": 1.202645,
"jobs": 2960,
"classes": 4096,
"positions": 4096,
"matches": 0
},
"validation": {
"type": "validation",
"complete_roots_equal": true,
"complete_matches_equal": true,
"matches": []
},
"setup_ms": 248.445216
},
"source_sha256": {
"pipeline_bench.cu": "249b6119832788d37643591407bc7eeebc086af452fe22cf0c756004a28596b0",
"cuda_bench.cu": "f762ea050d7c93c00903928f972e41106e917d37a4caceb79630bacd0f9316e1",
"grouped.hpp": "5d48c4a45e7f7b07a362c69b5163f48d44bd45d18e7f0f02b00bda0edaadeb23",
"run_pipeline.py": "a1aaea904d5a3a0d341ed1956e15f20af93c42c76205a2b8df108878f445ac59"
}
}

View file

@ -0,0 +1,14 @@
{"type":"setup","host_ms":220.229718}
{"type":"pipeline","mode":0,"round":0,"positions":1653,"classes":1653,"active_positions":1653,"jobs":138852,"matches":24,"host_ms":351.890247,"build_ms":0.123965,"root_ms":8.648427,"expand_ms":0.000189,"search_ms":343.117004}
{"type":"pipeline","mode":1,"round":0,"positions":1653,"classes":1653,"active_positions":1653,"jobs":138852,"matches":24,"host_ms":60.282088,"build_ms":0.106201,"root_ms":8.500842,"expand_ms":0.000189,"search_ms":51.674478}
{"type":"pipeline","mode":2,"round":0,"positions":1653,"classes":1,"active_positions":1653,"jobs":138852,"matches":24,"host_ms":54.114753,"build_ms":0.118106,"root_ms":0.32588,"expand_ms":0.297156,"search_ms":53.373222}
{"type":"pipeline","mode":3,"round":0,"positions":1653,"classes":1,"active_positions":1653,"jobs":138852,"matches":24,"host_ms":56.8665,"build_ms":0.0101,"root_ms":0.2025,"expand_ms":0.6349,"search_ms":56.0187}
{"type":"pipeline","mode":1,"round":1,"positions":1653,"classes":1653,"active_positions":1653,"jobs":138852,"matches":24,"host_ms":63.2884,"build_ms":0.113,"root_ms":9.1249,"expand_ms":0.0003,"search_ms":54.0495}
{"type":"pipeline","mode":2,"round":1,"positions":1653,"classes":1,"active_positions":1653,"jobs":138852,"matches":24,"host_ms":55.3725,"build_ms":0.1507,"root_ms":0.4095,"expand_ms":0.2649,"search_ms":54.5471}
{"type":"pipeline","mode":3,"round":1,"positions":1653,"classes":1,"active_positions":1653,"jobs":138852,"matches":24,"host_ms":55.7387,"build_ms":0.0109,"root_ms":0.2574,"expand_ms":0.7803,"search_ms":54.6898}
{"type":"pipeline","mode":0,"round":1,"positions":1653,"classes":1653,"active_positions":1653,"jobs":138852,"matches":24,"host_ms":374.3942,"build_ms":0.114,"root_ms":8.904,"expand_ms":0.0001,"search_ms":365.3759}
{"type":"pipeline","mode":2,"round":2,"positions":1653,"classes":1,"active_positions":1653,"jobs":138852,"matches":24,"host_ms":56.1846,"build_ms":0.133,"root_ms":0.3246,"expand_ms":0.2974,"search_ms":55.4289}
{"type":"pipeline","mode":3,"round":2,"positions":1653,"classes":1,"active_positions":1653,"jobs":138852,"matches":24,"host_ms":57.1526,"build_ms":0.0088,"root_ms":0.1615,"expand_ms":0.6781,"search_ms":56.3039}
{"type":"pipeline","mode":0,"round":2,"positions":1653,"classes":1653,"active_positions":1653,"jobs":138852,"matches":24,"host_ms":364.022951,"build_ms":0.1147,"root_ms":8.7547,"expand_ms":0.0001,"search_ms":355.153251}
{"type":"pipeline","mode":1,"round":2,"positions":1653,"classes":1653,"active_positions":1653,"jobs":138852,"matches":24,"host_ms":62.015757,"build_ms":0.113887,"root_ms":8.742087,"expand_ms":0.000191,"search_ms":53.159211}
{"type":"validation","complete_roots_equal":true,"complete_matches_equal":true,"matches":[[10358701894766,51069,419124],[15959335054446,51069,419124],[18914276748398,51069,419124],[24514909908078,51069,419124],[27469851602030,51069,419124],[33070484761710,51069,419124],[36025426455662,51069,419124],[41626059615342,51069,419124],[44581001309294,51069,419124],[50181634468974,51069,419124],[53136576162926,51069,419124],[58737209322606,51069,419124],[61692151016558,51069,419124],[67292784176238,51069,419124],[70247725870190,51069,419124],[75848359029870,51069,419124],[78803300723822,51069,419124],[84403933883502,51069,419124],[87358875577454,51069,419124],[92959508737134,51069,419124],[95914450431086,51069,419124],[101515083590766,51069,419124],[104470025284718,51069,419124],[110070658444398,51069,419124]]}

View file

@ -0,0 +1,14 @@
{"type":"setup","host_ms":242.015308}
{"type":"pipeline","mode":0,"round":0,"positions":32768,"classes":32768,"active_positions":32768,"jobs":15424,"matches":0,"host_ms":172.222139,"build_ms":5.020376,"root_ms":125.961985,"expand_ms":0.000192,"search_ms":41.239203}
{"type":"pipeline","mode":1,"round":0,"positions":32768,"classes":32768,"active_positions":32768,"jobs":15424,"matches":0,"host_ms":141.138417,"build_ms":4.616912,"root_ms":130.393185,"expand_ms":0.000287,"search_ms":6.127841}
{"type":"pipeline","mode":2,"round":0,"positions":32768,"classes":512,"active_positions":32768,"jobs":15424,"matches":0,"host_ms":14.093525,"build_ms":5.009729,"root_ms":2.227974,"expand_ms":0.638962,"search_ms":6.216476}
{"type":"pipeline","mode":3,"round":0,"positions":32768,"classes":512,"active_positions":1216,"jobs":15424,"matches":0,"host_ms":9.527453,"build_ms":0.399052,"root_ms":2.04888,"expand_ms":0.821317,"search_ms":6.257916}
{"type":"pipeline","mode":1,"round":1,"positions":32768,"classes":32768,"active_positions":32768,"jobs":15424,"matches":0,"host_ms":137.613046,"build_ms":4.711591,"root_ms":126.754716,"expand_ms":9.6e-05,"search_ms":6.145971}
{"type":"pipeline","mode":2,"round":1,"positions":32768,"classes":512,"active_positions":32768,"jobs":15424,"matches":0,"host_ms":14.235207,"build_ms":5.358898,"root_ms":2.203034,"expand_ms":0.604141,"search_ms":6.068846}
{"type":"pipeline","mode":3,"round":1,"positions":32768,"classes":512,"active_positions":1216,"jobs":15424,"matches":0,"host_ms":9.585776,"build_ms":0.416318,"root_ms":1.860291,"expand_ms":0.534307,"search_ms":6.774668}
{"type":"pipeline","mode":0,"round":1,"positions":32768,"classes":32768,"active_positions":32768,"jobs":15424,"matches":0,"host_ms":171.867118,"build_ms":4.452687,"root_ms":126.737258,"expand_ms":0.000288,"search_ms":40.676693}
{"type":"pipeline","mode":2,"round":2,"positions":32768,"classes":512,"active_positions":32768,"jobs":15424,"matches":0,"host_ms":15.318882,"build_ms":5.280144,"root_ms":2.701464,"expand_ms":0.670138,"search_ms":6.666944}
{"type":"pipeline","mode":3,"round":2,"positions":32768,"classes":512,"active_positions":1216,"jobs":15424,"matches":0,"host_ms":10.647196,"build_ms":0.441931,"root_ms":2.114877,"expand_ms":0.690187,"search_ms":7.400009}
{"type":"pipeline","mode":0,"round":2,"positions":32768,"classes":32768,"active_positions":32768,"jobs":15424,"matches":0,"host_ms":174.051349,"build_ms":4.55245,"root_ms":127.973647,"expand_ms":0.000192,"search_ms":41.524773}
{"type":"pipeline","mode":1,"round":2,"positions":32768,"classes":32768,"active_positions":32768,"jobs":15424,"matches":0,"host_ms":144.526135,"build_ms":4.499307,"root_ms":133.867236,"expand_ms":0.000192,"search_ms":6.159304}
{"type":"validation","complete_roots_equal":true,"complete_matches_equal":true,"matches":[]}

View file

@ -0,0 +1,14 @@
{"type":"setup","host_ms":219.927973}
{"type":"pipeline","mode":0,"round":0,"positions":52213,"classes":52213,"active_positions":52213,"jobs":1693228,"matches":0,"host_ms":4362.48845,"build_ms":7.490479,"root_ms":252.85323,"expand_ms":0.000286,"search_ms":4102.144074}
{"type":"pipeline","mode":1,"round":0,"positions":52213,"classes":52213,"active_positions":52213,"jobs":1693228,"matches":0,"host_ms":909.690741,"build_ms":7.012591,"root_ms":242.747725,"expand_ms":0.000183,"search_ms":659.929967}
{"type":"pipeline","mode":2,"round":0,"positions":52213,"classes":32,"active_positions":52213,"jobs":1693228,"matches":0,"host_ms":636.817316,"build_ms":7.196841,"root_ms":0.554217,"expand_ms":1.022633,"search_ms":628.04335}
{"type":"pipeline","mode":3,"round":0,"positions":52213,"classes":32,"active_positions":52213,"jobs":1693228,"matches":0,"host_ms":633.461125,"build_ms":0.338158,"root_ms":0.504258,"expand_ms":8.844275,"search_ms":623.77425}
{"type":"pipeline","mode":1,"round":1,"positions":52213,"classes":52213,"active_positions":52213,"jobs":1693228,"matches":0,"host_ms":915.445942,"build_ms":7.53445,"root_ms":245.545208,"expand_ms":9.2e-05,"search_ms":662.365642}
{"type":"pipeline","mode":2,"round":1,"positions":52213,"classes":32,"active_positions":52213,"jobs":1693228,"matches":0,"host_ms":656.710025,"build_ms":9.4644,"root_ms":0.576767,"expand_ms":1.500033,"search_ms":645.168458}
{"type":"pipeline","mode":3,"round":1,"positions":52213,"classes":32,"active_positions":52213,"jobs":1693228,"matches":0,"host_ms":676.742292,"build_ms":0.3428,"root_ms":0.671,"expand_ms":9.1207,"search_ms":666.607392}
{"type":"pipeline","mode":0,"round":1,"positions":52213,"classes":52213,"active_positions":52213,"jobs":1693228,"matches":0,"host_ms":4691.310731,"build_ms":7.216464,"root_ms":255.097691,"expand_ms":0.000286,"search_ms":4428.995719}
{"type":"pipeline","mode":2,"round":2,"positions":52213,"classes":32,"active_positions":52213,"jobs":1693228,"matches":0,"host_ms":685.115982,"build_ms":7.652735,"root_ms":0.58709,"expand_ms":1.326998,"search_ms":675.548969}
{"type":"pipeline","mode":3,"round":2,"positions":52213,"classes":32,"active_positions":52213,"jobs":1693228,"matches":0,"host_ms":681.412155,"build_ms":0.344485,"root_ms":0.473976,"expand_ms":8.571836,"search_ms":672.021573}
{"type":"pipeline","mode":0,"round":2,"positions":52213,"classes":52213,"active_positions":52213,"jobs":1693228,"matches":0,"host_ms":4816.532778,"build_ms":9.669654,"root_ms":263.964214,"expand_ms":0.000191,"search_ms":4542.898147}
{"type":"pipeline","mode":1,"round":2,"positions":52213,"classes":52213,"active_positions":52213,"jobs":1693228,"matches":0,"host_ms":980.983116,"build_ms":7.505432,"root_ms":259.835073,"expand_ms":0.000191,"search_ms":713.641749}
{"type":"validation","complete_roots_equal":true,"complete_matches_equal":true,"matches":[]}

View file

@ -0,0 +1,14 @@
{"type":"setup","host_ms":216.555239}
{"type":"pipeline","mode":0,"round":0,"positions":4096,"classes":4096,"active_positions":4096,"jobs":2960,"matches":0,"host_ms":22.564546,"build_ms":0.29315,"root_ms":15.171827,"expand_ms":0.000192,"search_ms":7.099377}
{"type":"pipeline","mode":1,"round":0,"positions":4096,"classes":4096,"active_positions":4096,"jobs":2960,"matches":0,"host_ms":17.388386,"build_ms":0.316459,"root_ms":15.843212,"expand_ms":0.000192,"search_ms":1.228427}
{"type":"pipeline","mode":2,"round":0,"positions":4096,"classes":4096,"active_positions":4096,"jobs":2960,"matches":0,"host_ms":19.225847,"build_ms":1.497691,"root_ms":15.909497,"expand_ms":0.624573,"search_ms":1.193798}
{"type":"pipeline","mode":3,"round":0,"positions":4096,"classes":4096,"active_positions":118,"jobs":2960,"matches":0,"host_ms":17.880678,"build_ms":1.123676,"root_ms":14.852298,"expand_ms":0.623134,"search_ms":1.281474}
{"type":"pipeline","mode":1,"round":1,"positions":4096,"classes":4096,"active_positions":4096,"jobs":2960,"matches":0,"host_ms":17.902261,"build_ms":0.291998,"root_ms":16.411382,"expand_ms":0.000287,"search_ms":1.19821}
{"type":"pipeline","mode":2,"round":1,"positions":4096,"classes":4096,"active_positions":4096,"jobs":2960,"matches":0,"host_ms":19.238988,"build_ms":1.595823,"root_ms":15.836689,"expand_ms":0.631288,"search_ms":1.174708}
{"type":"pipeline","mode":3,"round":1,"positions":4096,"classes":4096,"active_positions":118,"jobs":2960,"matches":0,"host_ms":21.575071,"build_ms":1.05058,"root_ms":17.458508,"expand_ms":0.716758,"search_ms":2.349129}
{"type":"pipeline","mode":0,"round":1,"positions":4096,"classes":4096,"active_positions":4096,"jobs":2960,"matches":0,"host_ms":33.127423,"build_ms":0.307347,"root_ms":24.924514,"expand_ms":0.000192,"search_ms":7.895082}
{"type":"pipeline","mode":2,"round":2,"positions":4096,"classes":4096,"active_positions":4096,"jobs":2960,"matches":0,"host_ms":20.589721,"build_ms":1.355912,"root_ms":17.315675,"expand_ms":0.630137,"search_ms":1.287517}
{"type":"pipeline","mode":3,"round":2,"positions":4096,"classes":4096,"active_positions":118,"jobs":2960,"matches":0,"host_ms":19.501921,"build_ms":1.103531,"root_ms":16.471047,"expand_ms":0.668987,"search_ms":1.257972}
{"type":"pipeline","mode":0,"round":2,"positions":4096,"classes":4096,"active_positions":4096,"jobs":2960,"matches":0,"host_ms":24.022332,"build_ms":0.288545,"root_ms":16.179721,"expand_ms":0.000191,"search_ms":7.553683}
{"type":"pipeline","mode":1,"round":2,"positions":4096,"classes":4096,"active_positions":4096,"jobs":2960,"matches":0,"host_ms":18.798496,"build_ms":0.350033,"root_ms":16.509706,"expand_ms":0.000191,"search_ms":1.938279}
{"type":"validation","complete_roots_equal":true,"complete_matches_equal":true,"matches":[]}

View file

@ -0,0 +1,6 @@
{"type":"setup","host_ms":200.876289}
{"type":"pipeline","mode":0,"round":0,"positions":32768,"classes":32768,"active_positions":32768,"jobs":15424,"matches":0,"host_ms":152.132767,"build_ms":4.096027,"root_ms":113.387564,"expand_ms":0.000184,"search_ms":34.648623}
{"type":"pipeline","mode":1,"round":0,"positions":32768,"classes":32768,"active_positions":32768,"jobs":15424,"matches":0,"host_ms":124.087013,"build_ms":4.152926,"root_ms":113.998689,"expand_ms":0.000184,"search_ms":5.934844}
{"type":"pipeline","mode":2,"round":0,"positions":32768,"classes":512,"active_positions":32768,"jobs":15424,"matches":0,"host_ms":13.605316,"build_ms":5.613835,"root_ms":1.992268,"expand_ms":0.604117,"search_ms":5.394911}
{"type":"pipeline","mode":3,"round":0,"positions":32768,"classes":512,"active_positions":1216,"jobs":15424,"matches":0,"host_ms":9.609161,"build_ms":1.342779,"root_ms":2.238581,"expand_ms":0.603472,"search_ms":5.424052}
{"type":"validation","complete_roots_equal":true,"complete_matches_equal":true,"matches":[]}

View file

@ -0,0 +1,6 @@
{"type":"setup","host_ms":175.300766}
{"type":"pipeline","mode":0,"round":0,"positions":21,"classes":21,"active_positions":21,"jobs":474,"matches":24,"host_ms":1.476311,"build_ms":0.003135,"root_ms":0.17549,"expand_ms":0,"search_ms":1.297501}
{"type":"pipeline","mode":1,"round":0,"positions":21,"classes":21,"active_positions":21,"jobs":474,"matches":24,"host_ms":0.505168,"build_ms":0.004611,"root_ms":0.175213,"expand_ms":9.3e-05,"search_ms":0.325159}
{"type":"pipeline","mode":2,"round":0,"positions":21,"classes":20,"active_positions":21,"jobs":474,"matches":24,"host_ms":0.834753,"build_ms":0.011158,"root_ms":0.242071,"expand_ms":0.210348,"search_ms":0.370991}
{"type":"pipeline","mode":3,"round":0,"positions":21,"classes":20,"active_positions":13,"jobs":474,"matches":24,"host_ms":0.782097,"build_ms":0.004335,"root_ms":0.1967,"expand_ms":0.261529,"search_ms":0.319533}
{"type":"validation","complete_roots_equal":true,"complete_matches_equal":true,"matches":[[10358701894766,51069,419124],[15959335054446,51069,419124],[18914276748398,51069,419124],[24514909908078,51069,419124],[27469851602030,51069,419124],[33070484761710,51069,419124],[36025426455662,51069,419124],[41626059615342,51069,419124],[44581001309294,51069,419124],[50181634468974,51069,419124],[53136576162926,51069,419124],[58737209322606,51069,419124],[61692151016558,51069,419124],[67292784176238,51069,419124],[70247725870190,51069,419124],[75848359029870,51069,419124],[78803300723822,51069,419124],[84403933883502,51069,419124],[87358875577454,51069,419124],[92959508737134,51069,419124],[95914450431086,51069,419124],[101515083590766,51069,419124],[104470025284718,51069,419124],[110070658444398,51069,419124]]}

View file

@ -0,0 +1,361 @@
{
"metadata": {
"date": "2026-10-11T10:51:13.411084+08:00",
"gpu": "name, driver_version\nNVIDIA GeForce RTX 3060 Laptop GPU, 596.49\n"
},
"known_lifts": {
"0": {
"host_ms": 364.022951,
"build_ms": 0.1147,
"root_ms": 8.7547,
"expand_ms": 0.0001,
"search_ms": 355.153251,
"jobs": 138852,
"classes": 1653,
"positions": 1653,
"active_positions": 1653,
"matches": 24
},
"1": {
"host_ms": 62.015757,
"build_ms": 0.113,
"root_ms": 8.742087,
"expand_ms": 0.000191,
"search_ms": 53.159211,
"jobs": 138852,
"classes": 1653,
"positions": 1653,
"active_positions": 1653,
"matches": 24
},
"2": {
"host_ms": 55.3725,
"build_ms": 0.133,
"root_ms": 0.32588,
"expand_ms": 0.297156,
"search_ms": 54.5471,
"jobs": 138852,
"classes": 1,
"positions": 1653,
"active_positions": 1653,
"matches": 24
},
"3": {
"host_ms": 56.8665,
"build_ms": 0.0101,
"root_ms": 0.2025,
"expand_ms": 0.6781,
"search_ms": 56.0187,
"jobs": 138852,
"classes": 1,
"positions": 1653,
"active_positions": 1653,
"matches": 24
},
"validation": {
"type": "validation",
"complete_roots_equal": true,
"complete_matches_equal": true,
"matches": [
[
10358701894766,
51069,
419124
],
[
15959335054446,
51069,
419124
],
[
18914276748398,
51069,
419124
],
[
24514909908078,
51069,
419124
],
[
27469851602030,
51069,
419124
],
[
33070484761710,
51069,
419124
],
[
36025426455662,
51069,
419124
],
[
41626059615342,
51069,
419124
],
[
44581001309294,
51069,
419124
],
[
50181634468974,
51069,
419124
],
[
53136576162926,
51069,
419124
],
[
58737209322606,
51069,
419124
],
[
61692151016558,
51069,
419124
],
[
67292784176238,
51069,
419124
],
[
70247725870190,
51069,
419124
],
[
75848359029870,
51069,
419124
],
[
78803300723822,
51069,
419124
],
[
84403933883502,
51069,
419124
],
[
87358875577454,
51069,
419124
],
[
92959508737134,
51069,
419124
],
[
95914450431086,
51069,
419124
],
[
101515083590766,
51069,
419124
],
[
104470025284718,
51069,
419124
],
[
110070658444398,
51069,
419124
]
]
},
"setup_ms": 220.229718
},
"nonempty32": {
"0": {
"host_ms": 4691.310731,
"build_ms": 7.490479,
"root_ms": 255.097691,
"expand_ms": 0.000286,
"search_ms": 4428.995719,
"jobs": 1693228,
"classes": 52213,
"positions": 52213,
"active_positions": 52213,
"matches": 0
},
"1": {
"host_ms": 915.445942,
"build_ms": 7.505432,
"root_ms": 245.545208,
"expand_ms": 0.000183,
"search_ms": 662.365642,
"jobs": 1693228,
"classes": 52213,
"positions": 52213,
"active_positions": 52213,
"matches": 0
},
"2": {
"host_ms": 656.710025,
"build_ms": 7.652735,
"root_ms": 0.576767,
"expand_ms": 1.326998,
"search_ms": 645.168458,
"jobs": 1693228,
"classes": 32,
"positions": 52213,
"active_positions": 52213,
"matches": 0
},
"3": {
"host_ms": 676.742292,
"build_ms": 0.3428,
"root_ms": 0.504258,
"expand_ms": 8.844275,
"search_ms": 666.607392,
"jobs": 1693228,
"classes": 32,
"positions": 52213,
"active_positions": 52213,
"matches": 0
},
"validation": {
"type": "validation",
"complete_roots_equal": true,
"complete_matches_equal": true,
"matches": []
},
"setup_ms": 219.927973
},
"mixed512": {
"0": {
"host_ms": 172.222139,
"build_ms": 4.55245,
"root_ms": 126.737258,
"expand_ms": 0.000192,
"search_ms": 41.239203,
"jobs": 15424,
"classes": 32768,
"positions": 32768,
"active_positions": 32768,
"matches": 0
},
"1": {
"host_ms": 141.138417,
"build_ms": 4.616912,
"root_ms": 130.393185,
"expand_ms": 0.000192,
"search_ms": 6.145971,
"jobs": 15424,
"classes": 32768,
"positions": 32768,
"active_positions": 32768,
"matches": 0
},
"2": {
"host_ms": 14.235207,
"build_ms": 5.280144,
"root_ms": 2.227974,
"expand_ms": 0.638962,
"search_ms": 6.216476,
"jobs": 15424,
"classes": 512,
"positions": 32768,
"active_positions": 32768,
"matches": 0
},
"3": {
"host_ms": 9.585776,
"build_ms": 0.416318,
"root_ms": 2.04888,
"expand_ms": 0.690187,
"search_ms": 6.774668,
"jobs": 15424,
"classes": 512,
"positions": 32768,
"active_positions": 1216,
"matches": 0
},
"validation": {
"type": "validation",
"complete_roots_equal": true,
"complete_matches_equal": true,
"matches": []
},
"setup_ms": 242.015308
},
"random4096": {
"0": {
"host_ms": 24.022332,
"build_ms": 0.29315,
"root_ms": 16.179721,
"expand_ms": 0.000192,
"search_ms": 7.553683,
"jobs": 2960,
"classes": 4096,
"positions": 4096,
"active_positions": 4096,
"matches": 0
},
"1": {
"host_ms": 17.902261,
"build_ms": 0.316459,
"root_ms": 16.411382,
"expand_ms": 0.000192,
"search_ms": 1.228427,
"jobs": 2960,
"classes": 4096,
"positions": 4096,
"active_positions": 4096,
"matches": 0
},
"2": {
"host_ms": 19.238988,
"build_ms": 1.497691,
"root_ms": 15.909497,
"expand_ms": 0.630137,
"search_ms": 1.193798,
"jobs": 2960,
"classes": 4096,
"positions": 4096,
"active_positions": 4096,
"matches": 0
},
"3": {
"host_ms": 19.501921,
"build_ms": 1.103531,
"root_ms": 16.471047,
"expand_ms": 0.668987,
"search_ms": 1.281474,
"jobs": 2960,
"classes": 4096,
"positions": 4096,
"active_positions": 118,
"matches": 0
},
"validation": {
"type": "validation",
"complete_roots_equal": true,
"complete_matches_equal": true,
"matches": []
},
"setup_ms": 216.555239
},
"source_sha256": {
"pipeline_bench.cu": "31da815aa0ee8904c702e55d2d685282fc64bfada24dd208e151faac5c55c37c",
"cuda_bench.cu": "3e1fd6fe3bdb87ac68fe853dc4e6d2275d6aa00a692c7d630391fd12c0105c20",
"grouped.hpp": "5d48c4a45e7f7b07a362c69b5163f48d44bd45d18e7f0f02b00bda0edaadeb23",
"run_pipeline.py": "ce3f9e01fad8978541c581233bfeaa4023acade24bbc736f479be6ac14e88591"
}
}

View file

@ -0,0 +1,6 @@
{"type":"setup","host_ms":197.591869}
{"type":"pipeline","mode":0,"round":0,"positions":1653,"classes":1653,"active_positions":1653,"jobs":0,"matches":0,"host_ms":5.571692,"build_ms":0.090188,"root_ms":5.379603,"expand_ms":0,"search_ms":0.101716}
{"type":"pipeline","mode":1,"round":0,"positions":1653,"classes":1653,"active_positions":1653,"jobs":0,"matches":0,"host_ms":5.729661,"build_ms":0.1019,"root_ms":5.497826,"expand_ms":0,"search_ms":0.12975}
{"type":"pipeline","mode":2,"round":0,"positions":1653,"classes":1,"active_positions":1653,"jobs":0,"matches":0,"host_ms":0.56059,"build_ms":0.10771,"root_ms":0.251016,"expand_ms":0.131594,"search_ms":0.070177}
{"type":"pipeline","mode":3,"round":0,"positions":1653,"classes":1,"active_positions":0,"jobs":0,"matches":0,"host_ms":0.230821,"build_ms":0.006363,"root_ms":0.083272,"expand_ms":0.071838,"search_ms":0.069348}
{"type":"validation","complete_roots_equal":true,"complete_matches_equal":true,"matches":[]}

View file

@ -0,0 +1 @@
{"q_checks":5000000,"group_masks":888128,"partial_filter_survivors":159120,"known_filter_survivors":36,"passed":true}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,40 @@
{"type":"device","name":"NVIDIA GeForce RTX 3060 Laptop GPU","positions":1}
{"type":"search_timing","mode":3,"round":0,"kernel_ms":0.3235839903,"scan_ms":0.46062,"matches":24}
{"type":"search_timing","mode":4,"round":0,"kernel_ms":0.2693119943,"scan_ms":0.393283,"matches":24}
{"type":"search_timing","mode":5,"round":0,"kernel_ms":0.2897920012,"scan_ms":0.44485,"matches":24}
{"type":"search_timing","mode":6,"round":0,"kernel_ms":0.2846719921,"scan_ms":0.431015,"matches":24}
{"type":"search_timing","mode":7,"round":0,"kernel_ms":0.1566720009,"scan_ms":0.292181,"matches":24}
{"type":"search_timing","mode":4,"round":1,"kernel_ms":0.2682879865,"scan_ms":0.380609,"matches":24}
{"type":"search_timing","mode":5,"round":1,"kernel_ms":0.2959359884,"scan_ms":0.421824,"matches":24}
{"type":"search_timing","mode":6,"round":1,"kernel_ms":0.2887679935,"scan_ms":0.400152,"matches":24}
{"type":"search_timing","mode":7,"round":1,"kernel_ms":0.1556479931,"scan_ms":0.275249,"matches":24}
{"type":"search_timing","mode":3,"round":1,"kernel_ms":0.3235839903,"scan_ms":0.449784,"matches":24}
{"type":"search_timing","mode":5,"round":2,"kernel_ms":0.2938880026,"scan_ms":0.40615,"matches":24}
{"type":"search_timing","mode":6,"round":2,"kernel_ms":0.2897920012,"scan_ms":0.40199,"matches":24}
{"type":"search_timing","mode":7,"round":2,"kernel_ms":0.1566720009,"scan_ms":0.269735,"matches":24}
{"type":"search_timing","mode":3,"round":2,"kernel_ms":0.3225600123,"scan_ms":0.437013,"matches":24}
{"type":"search_timing","mode":4,"round":2,"kernel_ms":0.2693119943,"scan_ms":0.3779,"matches":24}
{"type":"search_timing","mode":6,"round":3,"kernel_ms":0.2897920012,"scan_ms":0.411375,"matches":24}
{"type":"search_timing","mode":7,"round":3,"kernel_ms":0.1556479931,"scan_ms":0.269929,"matches":24}
{"type":"search_timing","mode":3,"round":3,"kernel_ms":0.3194879889,"scan_ms":0.427629,"matches":24}
{"type":"search_timing","mode":4,"round":3,"kernel_ms":0.2682879865,"scan_ms":0.375288,"matches":24}
{"type":"search_timing","mode":5,"round":3,"kernel_ms":0.2969599962,"scan_ms":0.414665,"matches":24}
{"type":"search_timing","mode":7,"round":4,"kernel_ms":0.1566720009,"scan_ms":0.268187,"matches":24}
{"type":"search_timing","mode":3,"round":4,"kernel_ms":0.3235839903,"scan_ms":0.426952,"matches":24}
{"type":"search_timing","mode":4,"round":4,"kernel_ms":0.2682879865,"scan_ms":0.425307,"matches":24}
{"type":"search_timing","mode":5,"round":4,"kernel_ms":0.2949120104,"scan_ms":0.415051,"matches":24}
{"type":"search_timing","mode":6,"round":4,"kernel_ms":0.2897920012,"scan_ms":0.407022,"matches":24}
{"type":"search_timing","mode":3,"round":5,"kernel_ms":0.3235839903,"scan_ms":0.427339,"matches":24}
{"type":"search_timing","mode":4,"round":5,"kernel_ms":0.2631680071,"scan_ms":0.37432,"matches":24}
{"type":"search_timing","mode":5,"round":5,"kernel_ms":0.2949120104,"scan_ms":0.403248,"matches":24}
{"type":"search_timing","mode":6,"round":5,"kernel_ms":0.2846719921,"scan_ms":0.436142,"matches":24}
{"type":"search_timing","mode":7,"round":5,"kernel_ms":0.1505279988,"scan_ms":0.388832,"matches":24}
{"type":"search_timing","mode":4,"round":6,"kernel_ms":0.4679679871,"scan_ms":0.896375,"matches":24}
{"type":"search_timing","mode":5,"round":6,"kernel_ms":0.5027840137,"scan_ms":0.714295,"matches":24}
{"type":"search_timing","mode":6,"round":6,"kernel_ms":0.4864000082,"scan_ms":0.691172,"matches":24}
{"type":"search_timing","mode":7,"round":6,"kernel_ms":0.1587200016,"scan_ms":0.454428,"matches":24}
{"type":"search_timing","mode":3,"round":6,"kernel_ms":0.3205119967,"scan_ms":0.426854,"matches":24}
{"type":"search_info","root_ms":1.090559959,"jobs":84,"lower35":11010048,"matches":[[10358701894766,51069,419124],[15959335054446,51069,419124],[18914276748398,51069,419124],[24514909908078,51069,419124],[27469851602030,51069,419124],[33070484761710,51069,419124],[36025426455662,51069,419124],[41626059615342,51069,419124],[44581001309294,51069,419124],[50181634468974,51069,419124],[53136576162926,51069,419124],[58737209322606,51069,419124],[61692151016558,51069,419124],[67292784176238,51069,419124],[70247725870190,51069,419124],[75848359029870,51069,419124],[78803300723822,51069,419124],[84403933883502,51069,419124],[87358875577454,51069,419124],[92959508737134,51069,419124],[95914450431086,51069,419124],[101515083590766,51069,419124],[104470025284718,51069,419124],[110070658444398,51069,419124]]}
{"type":"periodic_validation","classes":1,"positions":1,"equal":true}
{"type":"root_counts","counts":[84]}
{"type":"process","ms":234.661262}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,40 @@
{"type":"device","name":"NVIDIA GeForce RTX 3060 Laptop GPU","positions":21}
{"type":"search_timing","mode":3,"round":0,"kernel_ms":1.288192034,"scan_ms":1.497474,"matches":24}
{"type":"search_timing","mode":4,"round":0,"kernel_ms":0.9256960154,"scan_ms":1.163402,"matches":24}
{"type":"search_timing","mode":5,"round":0,"kernel_ms":1.083392024,"scan_ms":1.280467,"matches":24}
{"type":"search_timing","mode":6,"round":0,"kernel_ms":1.010687947,"scan_ms":1.163015,"matches":24}
{"type":"search_timing","mode":7,"round":0,"kernel_ms":0.224255994,"scan_ms":0.397249,"matches":24}
{"type":"search_timing","mode":4,"round":1,"kernel_ms":0.922623992,"scan_ms":1.157113,"matches":24}
{"type":"search_timing","mode":5,"round":1,"kernel_ms":2.477056026,"scan_ms":2.639978,"matches":24}
{"type":"search_timing","mode":6,"round":1,"kernel_ms":1.007616043,"scan_ms":1.288401,"matches":24}
{"type":"search_timing","mode":7,"round":1,"kernel_ms":0.2191359997,"scan_ms":0.471262,"matches":24}
{"type":"search_timing","mode":3,"round":1,"kernel_ms":1.288192034,"scan_ms":1.444263,"matches":24}
{"type":"search_timing","mode":5,"round":2,"kernel_ms":1.078271985,"scan_ms":1.256764,"matches":24}
{"type":"search_timing","mode":6,"round":2,"kernel_ms":1.006592035,"scan_ms":1.21168,"matches":24}
{"type":"search_timing","mode":7,"round":2,"kernel_ms":0.2232320011,"scan_ms":0.403248,"matches":24}
{"type":"search_timing","mode":3,"round":2,"kernel_ms":1.288192034,"scan_ms":1.439328,"matches":24}
{"type":"search_timing","mode":4,"round":2,"kernel_ms":0.9277439713,"scan_ms":1.074297,"matches":24}
{"type":"search_timing","mode":6,"round":3,"kernel_ms":1.010687947,"scan_ms":1.17298,"matches":24}
{"type":"search_timing","mode":7,"round":3,"kernel_ms":0.2191359997,"scan_ms":0.391735,"matches":24}
{"type":"search_timing","mode":3,"round":3,"kernel_ms":1.28512001,"scan_ms":1.408369,"matches":24}
{"type":"search_timing","mode":4,"round":3,"kernel_ms":0.922623992,"scan_ms":1.240607,"matches":24}
{"type":"search_timing","mode":5,"round":3,"kernel_ms":1.338368058,"scan_ms":1.72406,"matches":24}
{"type":"search_timing","mode":7,"round":4,"kernel_ms":0.2273280025,"scan_ms":0.686431,"matches":24}
{"type":"search_timing","mode":3,"round":4,"kernel_ms":1.284096003,"scan_ms":1.587644,"matches":24}
{"type":"search_timing","mode":4,"round":4,"kernel_ms":0.9267200232,"scan_ms":1.158467,"matches":24}
{"type":"search_timing","mode":5,"round":4,"kernel_ms":1.08544004,"scan_ms":1.29943,"matches":24}
{"type":"search_timing","mode":6,"round":4,"kernel_ms":1.010687947,"scan_ms":1.240704,"matches":24}
{"type":"search_timing","mode":3,"round":5,"kernel_ms":1.289216042,"scan_ms":1.494572,"matches":24}
{"type":"search_timing","mode":4,"round":5,"kernel_ms":0.9267200232,"scan_ms":1.150921,"matches":24}
{"type":"search_timing","mode":5,"round":5,"kernel_ms":1.084416032,"scan_ms":1.289078,"matches":24}
{"type":"search_timing","mode":6,"round":5,"kernel_ms":1.010687947,"scan_ms":1.221837,"matches":24}
{"type":"search_timing","mode":7,"round":5,"kernel_ms":0.2201599926,"scan_ms":0.470488,"matches":24}
{"type":"search_timing","mode":4,"round":6,"kernel_ms":0.9277439713,"scan_ms":1.136892,"matches":24}
{"type":"search_timing","mode":5,"round":6,"kernel_ms":1.083392024,"scan_ms":1.321102,"matches":24}
{"type":"search_timing","mode":6,"round":6,"kernel_ms":1.781759977,"scan_ms":1.983442,"matches":24}
{"type":"search_timing","mode":7,"round":6,"kernel_ms":0.2252800018,"scan_ms":0.355744,"matches":24}
{"type":"search_timing","mode":3,"round":6,"kernel_ms":1.93740797,"scan_ms":2.027463,"matches":24}
{"type":"search_info","root_ms":1.161216021,"jobs":474,"lower35":62128128,"matches":[[10358701894766,51069,419124],[15959335054446,51069,419124],[18914276748398,51069,419124],[24514909908078,51069,419124],[27469851602030,51069,419124],[33070484761710,51069,419124],[36025426455662,51069,419124],[41626059615342,51069,419124],[44581001309294,51069,419124],[50181634468974,51069,419124],[53136576162926,51069,419124],[58737209322606,51069,419124],[61692151016558,51069,419124],[67292784176238,51069,419124],[70247725870190,51069,419124],[75848359029870,51069,419124],[78803300723822,51069,419124],[84403933883502,51069,419124],[87358875577454,51069,419124],[92959508737134,51069,419124],[95914450431086,51069,419124],[101515083590766,51069,419124],[104470025284718,51069,419124],[110070658444398,51069,419124]]}
{"type":"periodic_validation","classes":20,"positions":21,"equal":true}
{"type":"root_counts","counts":[84,152,16,0,2,20,61,22,0,1,35,30,20,29,0,2,0,0,0,0,0]}
{"type":"process","ms":276.458389}

View file

@ -0,0 +1,331 @@
{
"metadata": {
"date": "2026-10-11T09:46:12.120634+08:00",
"cpu_validation": {
"q_checks": 5000000,
"group_masks": 888128,
"partial_filter_survivors": 159120,
"known_filter_survivors": 36,
"passed": true
},
"gpu": "name, driver_version\nNVIDIA GeForce RTX 3060 Laptop GPU, 596.49\n"
},
"known": {
"3": 0.3235839903,
"4": 0.2682879865,
"5": 0.2949120104,
"6": 0.2897920012,
"7": 0.1566720009,
"info": {
"type": "search_info",
"root_ms": 1.090559959,
"jobs": 84,
"lower35": 11010048,
"matches": [
[
10358701894766,
51069,
419124
],
[
15959335054446,
51069,
419124
],
[
18914276748398,
51069,
419124
],
[
24514909908078,
51069,
419124
],
[
27469851602030,
51069,
419124
],
[
33070484761710,
51069,
419124
],
[
36025426455662,
51069,
419124
],
[
41626059615342,
51069,
419124
],
[
44581001309294,
51069,
419124
],
[
50181634468974,
51069,
419124
],
[
53136576162926,
51069,
419124
],
[
58737209322606,
51069,
419124
],
[
61692151016558,
51069,
419124
],
[
67292784176238,
51069,
419124
],
[
70247725870190,
51069,
419124
],
[
75848359029870,
51069,
419124
],
[
78803300723822,
51069,
419124
],
[
84403933883502,
51069,
419124
],
[
87358875577454,
51069,
419124
],
[
92959508737134,
51069,
419124
],
[
95914450431086,
51069,
419124
],
[
101515083590766,
51069,
419124
],
[
104470025284718,
51069,
419124
],
[
110070658444398,
51069,
419124
]
]
}
},
"stress": {
"3": 1.288192034,
"4": 0.9267200232,
"5": 1.084416032,
"6": 1.010687947,
"7": 0.2232320011,
"info": {
"type": "search_info",
"root_ms": 1.161216021,
"jobs": 474,
"lower35": 62128128,
"matches": [
[
10358701894766,
51069,
419124
],
[
15959335054446,
51069,
419124
],
[
18914276748398,
51069,
419124
],
[
24514909908078,
51069,
419124
],
[
27469851602030,
51069,
419124
],
[
33070484761710,
51069,
419124
],
[
36025426455662,
51069,
419124
],
[
41626059615342,
51069,
419124
],
[
44581001309294,
51069,
419124
],
[
50181634468974,
51069,
419124
],
[
53136576162926,
51069,
419124
],
[
58737209322606,
51069,
419124
],
[
61692151016558,
51069,
419124
],
[
67292784176238,
51069,
419124
],
[
70247725870190,
51069,
419124
],
[
75848359029870,
51069,
419124
],
[
78803300723822,
51069,
419124
],
[
84403933883502,
51069,
419124
],
[
87358875577454,
51069,
419124
],
[
92959508737134,
51069,
419124
],
[
95914450431086,
51069,
419124
],
[
101515083590766,
51069,
419124
],
[
104470025284718,
51069,
419124
],
[
110070658444398,
51069,
419124
]
]
}
},
"random4096": {
"3": 8.857600212,
"4": 5.859327793,
"5": 6.7450881,
"6": 5.53574419,
"7": 1.141759992,
"info": {
"type": "search_info",
"root_ms": 19.01977539,
"jobs": 2960,
"lower35": 387973120,
"matches": []
}
},
"random65536": {
"3": 130.1360626,
"4": 98.65420532,
"5": 114.5487366,
"6": 108.295166,
"7": 19.98233604,
"info": {
"type": "search_info",
"root_ms": 267.9224243,
"jobs": 45356,
"lower35": 5944901632,
"matches": []
}
},
"fresh65536": {
"3": 134.184967,
"4": 102.5822754,
"5": 118.9703674,
"6": 112.1454086,
"7": 20.44006348,
"info": {
"type": "search_info",
"root_ms": 277.3555298,
"jobs": 46148,
"lower35": 6048710656,
"matches": []
}
},
"source_sha256": {
"cuda_bench.cu": "f762ea050d7c93c00903928f972e41106e917d37a4caceb79630bacd0f9316e1",
"grouped.hpp": "5d48c4a45e7f7b07a362c69b5163f48d44bd45d18e7f0f02b00bda0edaadeb23",
"cpu_verify.cpp": "2e2b6799bd624b3e0a3022c2144c4a6f665c08de530d8f2846e6bc748ba6412f",
"run.py": "daca9d7de3463fd501a99b10d921974b73c206acc6e1438a246ae5729043c15e"
}
}

View file

@ -0,0 +1,28 @@
#!/usr/bin/env python3
import subprocess,json,statistics,hashlib,random,datetime
from pathlib import Path
HERE=Path(__file__).resolve().parent
POS=HERE.parent/'full_search_feasibility'/'positions'
OUT=HERE/'results'
OUT.mkdir(exist_ok=True)
subprocess.run(['nvcc','-O3','-std=c++17','-arch=sm_86',str(HERE/'cuda_bench.cu'),'-o','/tmp/slime_normal_cuda'],check=True)
subprocess.run(['g++','-O3','-std=c++17','-Wall','-Wextra',str(HERE/'cpu_verify.cpp'),'-o','/tmp/slime_normal_verify'],check=True)
validation=subprocess.check_output(['/tmp/slime_normal_verify'],text=True)
(OUT/'cpu_verify.json').write_text(validation)
rng=random.Random(2026101104)
fresh=HERE/'fresh65536.txt'
fresh.write_text(''.join(f'{rng.randrange(-1875000,1875000)} {rng.randrange(-1875000,1875000)}\n' for _ in range(65536)))
summary={'metadata':{'date':datetime.datetime.now().astimezone().isoformat(),'cpu_validation':json.loads(validation),'gpu':subprocess.check_output(['nvidia-smi','--query-gpu=name,driver_version','--format=csv'],text=True)}}
for name in ['known','stress','random4096','random65536','fresh65536']:
cmd=['/tmp/slime_normal_cuda',str(fresh if name=='fresh65536' else POS/(name+'.txt')),'normal','7']
r=subprocess.run(cmd,capture_output=True,text=True,timeout=300)
(OUT/(name+'.jsonl')).write_text(r.stdout)
(OUT/(name+'.stderr')).write_text(r.stderr)
if r.returncode: raise RuntimeError(r.stderr)
rows=[json.loads(s) for s in r.stdout.splitlines()]
summary[name]={str(m):statistics.median(v['kernel_ms'] for v in rows if v['type']=='search_timing' and v['mode']==m) for m in [3,4,5,6,7]}
summary[name]['info']=next(v for v in rows if v['type']=='search_info')
print(name,json.dumps(summary[name]),flush=True)
summary['source_sha256']={name:hashlib.sha256((HERE/name).read_bytes()).hexdigest() for name in ['cuda_bench.cu','grouped.hpp','cpu_verify.cpp','run.py']}
summary['shared_headers_sha256']={name:hashlib.sha256((HERE.parents[2]/'include'/'slime'/name).read_bytes()).hexdigest() for name in ['solver_core.hpp','upper_interval.hpp']}
(OUT/'summary.json').write_text(json.dumps(summary,indent=2))

View file

@ -0,0 +1,44 @@
#!/usr/bin/env python3
import subprocess,json,random,statistics,hashlib,datetime
from pathlib import Path
HERE=Path(__file__).resolve().parent
OLD=HERE.parent/'full_search_feasibility'
OUT=HERE/'pipeline_results'
POS=HERE/'pipeline_positions'
OUT.mkdir(exist_ok=True);POS.mkdir(exist_ok=True)
def lifts(x,z):
return [(xx,zz) for xx in range(-1875000+(x+1875000)%65536,1875000,65536)
for zz in range(-1875000+(z+1875000)%131072,1875000,131072)]
def save(name,coords):
p=POS/(name+'.txt');p.write_text(''.join(f'{x} {z}\n' for x,z in coords));return p
known=save('known_lifts',lifts(51069,419124))
rng=random.Random(2026101105)
coords=[]
classes=set()
while len(classes)<512:
c=(rng.randrange(65536),rng.randrange(131072))
if c in classes:continue
classes.add(c)
coords.extend(rng.sample(lifts(*c),64))
mixed=save('mixed512',coords)
cases={'known_lifts':known,'nonempty32':OLD/'positions/lifts.txt','mixed512':mixed,'random4096':OLD/'positions/random4096.txt'}
subprocess.run(['nvcc','-O3','-std=c++17','-arch=sm_86',str(HERE/'pipeline_bench.cu'),'-o','/tmp/slime_pipeline_cuda'],check=True)
summary={'metadata':{'date':datetime.datetime.now().astimezone().isoformat(),'gpu':subprocess.check_output(['nvidia-smi','--query-gpu=name,driver_version','--format=csv'],text=True)}}
for name,path in cases.items():
cmd=['/tmp/slime_pipeline_cuda',str(path),'3']
p=subprocess.run(cmd,capture_output=True,text=True,timeout=300)
(OUT/(name+'.jsonl')).write_text(p.stdout);(OUT/(name+'.stderr')).write_text(p.stderr)
if p.returncode:raise RuntimeError(p.stderr)
rows=[json.loads(l) for l in p.stdout.splitlines()]
d={}
for m in range(4):
a=[r for r in rows if r['type']=='pipeline' and r['mode']==m]
d[str(m)]={k:statistics.median(r[k] for r in a) for k in ['host_ms','build_ms','root_ms','expand_ms','search_ms','jobs','classes','positions','active_positions','matches']}
d['validation']=next(r for r in rows if r['type']=='validation')
d['setup_ms']=next(r['host_ms'] for r in rows if r['type']=='setup')
summary[name]=d
(OUT/'summary.json').write_text(json.dumps(summary,indent=2))
print(name,json.dumps({k:v for k,v in d.items() if k!='validation'}),flush=True)
summary['source_sha256']={n:hashlib.sha256((HERE/n).read_bytes()).hexdigest() for n in ['pipeline_bench.cu','cuda_bench.cu','grouped.hpp','run_pipeline.py']}
summary['shared_headers_sha256']={name:hashlib.sha256((HERE.parents[2]/'include'/'slime'/name).read_bytes()).hexdigest() for name in ['solver_core.hpp','upper_interval.hpp']}
(OUT/'summary.json').write_text(json.dumps(summary,indent=2))

View file

@ -0,0 +1,28 @@
#!/usr/bin/env python3
import json,subprocess,random,hashlib
from pathlib import Path
H=Path(__file__).resolve().parent
OLD=H.parent/'full_search_feasibility'
POS=H/'pipeline_positions';OUT=H/'pipeline_results'
rows=[json.loads(l) for l in (OLD/'results/random4096.jsonl').read_text().splitlines()]
counts=next(r['counts'] for r in rows if r['type']=='root_counts')
points=[tuple(map(int,l.split())) for l in (OLD/'positions/random4096.txt').read_text().splitlines()]
x,z=points[counts.index(0)]
zero=[(xx,zz) for xx in range(-1875000+(x+1875000)%65536,1875000,65536) for zz in range(-1875000+(z+1875000)%131072,1875000,131072)]
p=POS/'zero_lifts.txt';p.write_text(''.join(f'{x} {z}\n' for x,z in zero))
shuffled=(POS/'mixed512.txt').read_text().splitlines();random.Random(2026101106).shuffle(shuffled)
q=POS/'shuffled_mixed.txt';q.write_text('\n'.join(shuffled)+'\n')
subprocess.run(['nvcc','-O3','-std=c++17','-arch=sm_86',str(H/'pipeline_bench.cu'),'-o','/tmp/slime_pipeline_cuda'],check=True)
checks={}
for name,path in [('zero_lifts',p),('stress',OLD/'positions/stress.txt'),('shuffled_mixed',q)]:
r=subprocess.run(['/tmp/slime_pipeline_cuda',str(path),'1'],capture_output=True,text=True,timeout=120)
(OUT/(name+'.jsonl')).write_text(r.stdout);(OUT/(name+'.stderr')).write_text(r.stderr)
if r.returncode:raise RuntimeError(r.stderr)
rows=[json.loads(l) for l in r.stdout.splitlines()]
checks[name]={'validation':next(r for r in rows if r['type']=='validation'),'modes':[r for r in rows if r['type']=='pipeline']}
if name=='zero_lifts':assert all(r['jobs']==0 and r['matches']==0 for r in checks[name]['modes'])
if name=='stress':assert len(checks[name]['validation']['matches'])==24
print(name,'passed',flush=True)
checks['source_sha256']={n:hashlib.sha256((H/n).read_bytes()).hexdigest() for n in ['pipeline_bench.cu','cuda_bench.cu','grouped.hpp','verify_pipeline_edges.py']}
checks['shared_headers_sha256']={name:hashlib.sha256((H.parents[2]/'include'/'slime'/name).read_bytes()).hexdigest() for name in ['solver_core.hpp','upper_interval.hpp']}
(OUT/'edge_validation.json').write_text(json.dumps(checks,indent=2))