135 lines
8.9 KiB
Markdown
135 lines
8.9 KiB
Markdown
# 实验结论:定点求解显著提速,全世界目录仍不适合启动
|
||
|
||
日期:2026-10-11,Asia/Hong_Kong。硬件:RTX 3060 Laptop、Ryzen 7 5800H,WSL,CUDA 12.0。
|
||
|
||
## 结论
|
||
|
||
1. **保留输出差过滤+逐格区间求交。** GPU 搜索 kernel 在三组同任务对照中快 197~292 倍,完整输出一致。
|
||
2. **保留低位坐标类复用。** 52,213 个实际位置的完整低位根列表与 32 个代表类一致;它减少根生成,不能消除后续中间位枚举。
|
||
3. **否决低位位表查找替换。** 此 GPU 上查表比直接整数计算多耗时约 36%。
|
||
4. **保留按首个奇数格逆推拒绝尾部。** 相比逐格枚举全部尾部,128 坐标批次快约 24 倍,并覆盖多次拒绝和多个格子首次拒绝的情况。
|
||
5. **当前路线仍不足以生成全世界全部种子的目录。** 随机批次吞吐外推:首次输出分支约 0.9 年;包含拒绝重抽的完整分支约 16 年。这里已乐观地摊薄进程启动、复用低位根生成,不是实际跑完全世界,也不是所有可能算法的下界。
|
||
|
||
代码是独立实验,没有替换原来的正式入口。
|
||
|
||
## GPU 求解器对照
|
||
|
||
全部模式处理相同的 lower35 候选,完整预热后轮换顺序测量五轮,核对排序后的完整 `(world_seed,x,z)` 列表。
|
||
|
||
| 负载 | lower35 数 | 原排序事件求解器 | 仅区间求交 | 输出差+原求解器 | 输出差+区间求交 | 最佳相对原版 |
|
||
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
||
| 已知位置 `(51069,419124)` | 11,010,048 | 63.750 ms | 0.763 ms | 0.390 ms | **0.324 ms** | **197.0×** |
|
||
| 21 个压力/边界坐标 | 62,128,128 | 363.876 ms | 4.674 ms | 1.757 ms | **1.245 ms** | **292.2×** |
|
||
| 4096 个均匀随机坐标 | 387,973,120 | 2318.625 ms | 29.380 ms | 12.297 ms | **8.157 ms** | **284.2×** |
|
||
| 65536 个均匀随机坐标 | 5,944,901,632 | 未重测 | 407.659 ms | 175.974 ms | **131.670 ms** | — |
|
||
|
||
以上均为 CUDA event kernel 中位数,不包括低位根生成、CUDA 初始化、分配和传输。21 坐标组包含已知命中附近位置、原点、世界边界和 int32 边界;它不代表随机平均坐标。
|
||
|
||
已知位置和压力组均得到相同的 24 个种子。两个随机组没有命中。随机无命中不单独构成正确性证据,另有下面的独立校验。
|
||
|
||
主要收益来自更早排除不可能共同满足模 10 条件的候选:
|
||
|
||
```
|
||
delta_i = (q_i(0) - q_0(0)) mod 2^31
|
||
必要条件:delta_i mod 10 属于 {0,8}
|
||
```
|
||
|
||
原因是改变高 13 位,对所有输出施加相同的模 `2^31` 平移;两个最终输出都是 10 的倍数时,差模 `2^31` 只能具有上述余数。多数候选在几个格子后就失败,不再支付 25 格的事件排序成本。差过滤通过后,最多两个“区间+余数”做逐格求交,再完整 Java 验证。
|
||
|
||
## 根分布与全局工作量
|
||
|
||
确定性均匀随机抽样 65536 个锚点,两轴范围 `[-1875000,1874999]`:
|
||
|
||
| 指标 | 结果 |
|
||
| --- | ---: |
|
||
| 首次输出低位无根比例 | 96.9162% |
|
||
| 低 18 位根总数 | 45,356 |
|
||
| 每坐标平均根数 | 0.69208 |
|
||
| 平均数的正态近似 95% 区间 | 0.61054~0.77361 |
|
||
| 最大根数 | 1015 |
|
||
|
||
分布有较长尾部。置信区间只说明该抽样模型中的根数均值不确定性,不包含 GPU 频率、长期运行、分组调度及模型覆盖的误差。
|
||
|
||
按样本均值,世界的 `14,062,500,000,000` 个锚点仍约有:
|
||
|
||
```
|
||
14,062,500,000,000 × 0.69207763671875 × 131072
|
||
= 1.2756375 × 10^18 个 lower35 候选
|
||
```
|
||
|
||
新 kernel 在 65536 坐标批次中约处理 451.5 亿个 lower35/秒。把实测批次吞吐线性扩展到全部锚点,首次输出分支约 **0.895 年**。这已不适合用早先的“已知命中坐标耗时 × 所有坐标”去估计成几万年,但距离几周完成仍有明显差距。
|
||
|
||
## 坐标类复用和位表查找
|
||
|
||
归一化有效种子 `s=world_seed+T(x,z)` 后,图案相对坐标项的低 18 位在 X 上以 `65536`、Z 上以 `131072` 为周期。
|
||
|
||
选取 32 个有根的类,并展开成世界内全部 52,213 个实际锚点。程序逐一比较每个同类位置的**完整归一化低位根列表**,全部一致。
|
||
|
||
| 低位筛选负载 | 直接整数计算 | 32 KiB 位表查找 |
|
||
| --- | ---: | ---: |
|
||
| 65536 随机坐标 | **280.639 ms** | 380.533 ms |
|
||
| 32 个类代表 | **0.138 ms** | 0.209 ms |
|
||
| 52,213 个实际位置重复计算 | **293.866 ms** | 409.952 ms |
|
||
|
||
因此查表方案不保留。类复用在算法上成立,表中只比较筛选 kernel,未把归类、展开和传输成本当作零成本的实测完整方案。全世界最多 `2^33` 个类,按大批次根筛选吞吐粗略外推,代表类筛选约 10.2 小时;更高位求解仍须处理具体坐标,不能再乘一个“1637 倍”全流程加速。
|
||
|
||
首次输出无根并不排除拒绝重抽解,所以不能据此跳过完整语义的异常分支。
|
||
|
||
## 完整覆盖拒绝重抽
|
||
|
||
朴素补扫对 25 格分别枚举 `8 × 2^17` 个首次拒绝状态,共 26,214,400 个候选/坐标。
|
||
|
||
本轮新增的规范化补扫只枚举一次有效种子的低 18 位 `p`:
|
||
|
||
1. 从 p 算出每格首次输出的奇偶。
|
||
2. 若存在奇数格,选第一个。任何真实解必须在这一格首次拒绝,否则不可能返回 0。
|
||
3. 该格状态的低 18 位已确定,在拒绝区间中恰好有四个完整推进后状态与它一致;逆推这四个完整种子,执行全部格子的精确 Java 检查。
|
||
4. 若全部格子都是偶数,则为每一格补扫四个拒绝状态。
|
||
|
||
若一个坐标有 R 个全偶低位根,最多生成 `2^20 + 96R` 个补扫候选。无需假设“多个格子同时拒绝不可能”;选择首个奇数格的必要性对这种情况也成立。所有首次输出都被接受的真实解由普通分支覆盖,任何首次拒绝的真实解由补扫覆盖。最终并集去重。
|
||
|
||
| 对照任务 | 逐格朴素补扫 | 规范化补扫 | 去重命中数 |
|
||
| --- | ---: | ---: | ---: |
|
||
| 已知坐标的单格约束 | 0.032 ms | 0.026 ms | 104,848 |
|
||
| 同坐标前两格约束 | 0.065 ms | 0.053 ms | 20,888 |
|
||
| 同坐标前五格约束 | 0.139 ms | 0.084 ms | 109 |
|
||
| 128 坐标的完整 5×5 | 93.597 ms | **3.908 ms** | 0 |
|
||
|
||
两种补扫逐项比较完整去重列表,单格、多格的非空结果也一致。
|
||
|
||
## 同批完整流程:最终成本判断
|
||
|
||
在同一个 65536 随机坐标批次中,普通分支和规范化拒绝补扫顺序执行,合并、排序、去重;完整预热后测五轮:
|
||
|
||
| 区域 | 中位数 |
|
||
| --- | ---: |
|
||
| 一次低位根准备 kernel | 296.573 ms(单次) |
|
||
| 普通搜索 kernel | 129.157 ms |
|
||
| 完整拒绝补扫 kernel | 2283.082 ms |
|
||
| 两个 kernel 的每轮耗时之和 | **2413.373 ms** |
|
||
| 同步、回传、合并在内的 host scan | **2356.676 ms** |
|
||
|
||
另在 21 坐标压力组完成同样的完整流程,全部 24 个已知结果保留,无额外拒绝解;完整结果已与此前普通分支核对。
|
||
|
||
本环境观察到 CUDA event 累计时间比 host wall time 高约 2.4%;两种时钟口径分别保留,不用它们混合计算局部加速比。这一差异的原因未单独确定,长期外推只按数量级解释。
|
||
|
||
按同批完整测量,外推全世界为 **16.0~16.4 年**。这里不重复支付进程启动,低位筛选可按坐标类摊薄;尚未计入全世界调度、建表、长期频率波动和输出持久化等工程成本。不能宣称已实现完整世界扫描。
|
||
|
||
补扫约占计算时间的 95%。**即使完全删掉这个正确性成本,普通分支仍约需一年。** 因此结论不依赖于罕见分支是否必须支持:这轮优化值得用于定点反查和有限批次,但仍不应启动全世界目录生成。
|
||
|
||
## 正确性检查与复现
|
||
|
||
- CPU 独立直接枚举 4096 个高位平面,共 33,554,432 个完整种子,覆盖 1~25 格约束、随机坐标和已知命中平面。原求解器、区间求解器和输出差过滤版本的完整列表一致。
|
||
- 用单独的 Java 算术实现核对全部 1,048,576 个单格拒绝状态及逆推;其中存在 52,422 个首次输出为奇数、重抽后成功的例子,防止测试只覆盖空结果。
|
||
- CPU 核对 250,000 个格子的坐标周期;GPU 每批抽取最多 64 个坐标完整核对低位根表,并对所有重复坐标类比较完整根列表。
|
||
- GPU 四种求解器、两种根筛选、两种拒绝补扫分别完整核对结果,容量溢出会失败。
|
||
- GPU 与桌面共享,五轮原始数据、温度、驱动、源码哈希及每项命令保存在结果文件。早期对照和后补完整流程的源码哈希分别记录,计算 kernel 的算法一致。
|
||
|
||
```
|
||
python3 research/experiments/full_search_feasibility/run.py
|
||
# GPU 需可访问;无 GPU 时可单独编译运行 cpu_verify.cpp。
|
||
python3 research/experiments/full_search_feasibility/run.py --analyse-only
|
||
```
|
||
|
||
核心代码:[interval_solver.hpp](interval_solver.hpp)、[cuda_bench.cu](cuda_bench.cu)。
|
||
汇总:[results/summary.json](results/summary.json)。完整实验数据:[results/all.json](results/all.json)。
|