# 普通搜索: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)。