149 lines
9.2 KiB
Markdown
149 lines
9.2 KiB
Markdown
# 史莱姆区块搜索:逐步演示
|
||
|
||
这里保存视频/博客稿、按步骤编号的代码,以及已保存的实测结果。
|
||
|
||
统一教程见 [DOCUMENT.md](DOCUMENT.md),从 CPU/CUDA 枚举讲到当前算法的数学推导。
|
||
视频为 15 章,保留 CPU → CUDA → 按坐标分工 → outer sum,再讲归一化、低位筛根、
|
||
类根复用、预计算、16 候选组 mask、高位求解与各项效果。01–08 保留为教学基线;当前入口见
|
||
[`bench/slime-bench`](../bench/README.md),共用数学位于 [`include/slime/`](../include/README.md)。
|
||
演示代码在本目录,研究实现位于 `research/`。
|
||
|
||
先读 [BENCHMARK.md](BENCHMARK.md) 看实测结果;命令、原始 stdout、全部计时样本、
|
||
编译器与源码 SHA256 保存在 [results/latest.json](results/latest.json)。
|
||
|
||
Manim 视频工程位于 [video/](video/README.md),使用 uv 管理依赖;包含完整动画、
|
||
两集独立场景,以及渲染时生成的字幕、口播稿和章节时间轴。
|
||
|
||
## 位数与术语
|
||
|
||
“低 18 位取值”指种子除以 `2^18` 的余数;`lower35` 指低 35 位,`upper13` 指剩余的高 13 位。补上中间 17 位,就是保留已有的低 18 位,再枚举紧挨着它们的更高 17 位。
|
||
“低位筛选结果缓存”按低 18 位取值复用筛选结果。世界种子与锚点有效种子分别指原始输入和吸收锚点坐标项后的输入,不能混用。
|
||
|
||
## 代码顺序
|
||
|
||
| 步骤 | 文件 | 这一版改变什么 |
|
||
| --- | --- | --- |
|
||
| 01 | `01_cpu.cpp` | CPU 按 seed 分任务,内部顺序扫描位置 |
|
||
| 02 | `02_cuda_seed.cuh` | 相同循环搬到 CUDA,一 thread 处理一个 seed |
|
||
| 03 | `03_cuda_position.cuh` 的 `coordinateKernel` | 一 thread 固定坐标,先算图案的 X/Z 项,再遍历 seed 复用 |
|
||
| 04 | `04_cuda_outer_sum.cuh` | 16×16 tile,共享扩展后的 X/Z 轴项 |
|
||
| 完整教程 | [DOCUMENT.md](DOCUMENT.md) | 从状态空间、低位依赖与模运算结构推导搜索方法 |
|
||
| 07 | `07_residue.cu` | 固定 seed,完整低位坐标余数过滤后展开 |
|
||
| 08 | `08_upper_compare.cu` | 相同 lower35 平面,高 13 位枚举/解析受控比较 |
|
||
| 08 完整流程 | `08_seed_cpu.cpp`、`08_seed_cuda.cu` | 固定坐标,筛低 18 位取值 → 补上中间 17 位 → 求高 13 位 |
|
||
|
||
`cuda_steps.cu` 统一负责 02–04 的启动、预热、计时和结果一致性检查。
|
||
核心算术在 `common.hpp`,必须保留 Java int 回绕和符号扩展;这里使用显式无符号运算,
|
||
避免直接照抄根目录 C++ 中的有符号溢出。
|
||
03、04 都保持固定坐标后遍历 seed 的策略。
|
||
03 在每个坐标的 seed 循环外预计算 n 个 X 项和 n 个 Z 项,传给 `solidAxes`。
|
||
03 的坐标项为 thread 私有;04 进一步让相邻 thread 共享 tile 的轴项。
|
||
图案大小 1–8 在 host 端选择模板,让私有数组索引和检查循环可在编译时展开。
|
||
固定坐标旧版/新版的单独对照见 [results/stage3_polynomial_reuse.json](results/stage3_polynomial_reuse.json):
|
||
65536 seed × 1025×1025,5 轮 kernel 中位数 1537.888 → 915.371 ms,速度比 1.680×。
|
||
这个对照包含多项式复用及编译期图案大小展开,两个版本先后运行;主线 02/03 则轮换顺序测量。
|
||
01–04 都记录每一个命中的 `(world_seed,x,z)`,没有“一 seed 找到第一个位置就返回”的差异。
|
||
|
||
性能主线到 04 结束。随后读 [DOCUMENT.md](DOCUMENT.md),
|
||
探索随机数的状态空间、低位依赖和模运算结构,再引出 07–08 的候选生成与解析求解。
|
||
这部分用推导和例子说明性质,不把 XOR 的等价改写列作计时优化。
|
||
|
||
07、08 完整流程是从对应 `research/` 实现提取的教学快照,文件头注明来源,
|
||
经 `../research/slime_solver_core.hpp` 兼容转发共享 `../include/slime/solver_core.hpp`。
|
||
08 的单独高位比较是新写的受控实验;其他成熟算法没有重新复制一套数学核心。
|
||
因此 `show/` 在本仓库内构建,不能只拷贝这个目录后省略 `research` 头文件。
|
||
|
||
## 编译和测试
|
||
|
||
```bash
|
||
make -C show -j4
|
||
python3 show/test_steps.py --gpu
|
||
python3 show/benchmark.py --repeats 5
|
||
```
|
||
|
||
默认 CUDA 编译目标是本机 RTX 3060 Laptop 的 `sm_86`,需要 CUDA 12 或兼容工具链。
|
||
其他 GPU 可覆盖,例如 `make -C show NVCCFLAGS='-O3 -std=c++17 -arch=sm_89'`。
|
||
无 GPU 时可运行 `make -C show test-cpu`;GPU 测试需要宿主 GPU 可访问。
|
||
测试用独立 Python oracle 对比完整列表,包括非零起始 seed、跨低 48 位边界、
|
||
负坐标、int32 边界、部分 tile、已知命中、8 种首次输出拒绝尾部和输出溢出。
|
||
另外核对 upper13 的直接枚举、完整 CPU/CUDA seed 流程,以及余数坐标展开验证。
|
||
本次验证日志保存在 [results/tests.txt](results/tests.txt)。
|
||
|
||
## 单独演示前四步
|
||
|
||
主线在测试负载变化处画分界线,衔接版本在两边分别重测。A/B 使用 5 轮计时,C 使用 100 轮轮换计时,每版另做一次完整预热。
|
||
|
||
```bash
|
||
python3 show/benchmark.py --only-mapping --repeats 5
|
||
```
|
||
|
||
完整 CPU 对照和大地图 CUDA 扫描耗时较长,脚本为每项允许最多 10 分钟。
|
||
|
||
各组配置:
|
||
|
||
| 组 | 用途 | 相同工作量下比较的版本 | 负载 |
|
||
| --- | --- | --- | --- |
|
||
| A | CPU 搬到 CUDA | 01 → 02 | 65536 seed × 257×257 锚点 |
|
||
| B | 改变并行策略 | 02 → 03 | 65536 seed × 4097×4097 锚点 |
|
||
| C | 坐标扫描与 outer sum | 03 → 04 | 1 seed × 8193×8193 锚点 |
|
||
|
||
**A/B 分界处重测 02,B/C 分界处重测 03,只在组内计算速度比。**
|
||
A、B 保持 65536 个 seed,以已知命中点为中心扩大地图:A 为 257×257,B 为 4097×4097。
|
||
A 完整重扫 CPU,与 CUDA 的相同输入比较;B 改变线程策略,两版完整扫描相同候选集合。
|
||
B 的 GPU 两版本完整核对命中列表,独立 CPU 则核对同一 seed 列表下的 257×257 窗口;所有 GPU 命中另用 Python 精确验证。
|
||
原来的极端负载保存在 [results/mapping_diagnostics.json](results/mapping_diagnostics.json),可用于讲解并行度。
|
||
|
||
```bash
|
||
# A:CPU 与按 seed 的 CUDA,两边相同输入
|
||
show/bin/01_cpu --seed 61692151016558 --seeds 65536 \
|
||
--x0 50941 --z0 418996 --width 257 --height 257 -n 5 --repeats 5
|
||
show/bin/cuda_steps --seed 61692151016558 --seeds 65536 \
|
||
--x0 50941 --z0 418996 --width 257 --height 257 -n 5 --modes 2 --repeats 5
|
||
|
||
# ── 分界:换负载,重新测 02,再与 03 比 ──
|
||
# B:保持 seed 数量,把地图扩大
|
||
show/bin/cuda_steps --seed 61692151016558 --seeds 65536 \
|
||
--x0 49021 --z0 417076 --width 4097 --height 4097 \
|
||
-n 5 --modes 2,3 --repeats 5
|
||
|
||
# ── 分界:扩大地图、改为固定 seed,重新测 03 ──
|
||
# C:固定坐标与 outer sum
|
||
show/bin/cuda_steps --seed 61692151016558 --seeds 1 \
|
||
--x0 46973 --z0 415028 --width 8193 --height 8193 \
|
||
-n 5 --modes 3,4 --repeats 100
|
||
```
|
||
|
||
输出是 JSON,包含每轮耗时、中位数和完整排序后的命中元组。
|
||
`--capacity` 是可存的命中数,超过容量会失败,不能用截断的列表假装验证通过。
|
||
所有 CUDA 版本均有范围判断。高 16 位输入不同会保留原始 seed 标签,判断结果等价;
|
||
输出标签归一化后才能进行这种等价比较。
|
||
CPU 计时包含创建线程,GPU kernel 不含上下文创建,因此报告另给 GPU scan 计时,
|
||
完整 seed 流程还给独立进程全流程计时。
|
||
|
||
## 后面的步骤
|
||
|
||
```bash
|
||
show/bin/07_residue --seed 61692151016558 -n 5
|
||
show/bin/08_upper_compare --lower35 16420645998 --planes 65536 --repeats 5
|
||
show/bin/08_seed_cpu search --x 51069 --z 419124 -n 5 -p 16 --max-results 1000
|
||
show/bin/08_seed_cuda --x 51069 --z 419124 -n 5 --threads 256 --max-results 1000
|
||
```
|
||
|
||
`benchmark.py` 把三类任务分开记录:联合暴力候选的映射、固定 seed 的坐标搜索、
|
||
固定坐标的 seed 搜索。X/Z 独立筛轴试验已撤下,见 [试错报告](../research/XZ_FILTER_TRIAL_REPORT.md)。
|
||
每阶段完成后保存 JSON,整套完成后生成报告。命令默认超时 60 秒,A/B/C 分段测速允许最多 10 分钟。
|
||
默认整套会重跑 GPU 和 CPU 数据,不需要依赖研究记录中的旧数字。
|
||
只修改前四步的测试参数时,可以运行 `python3 show/benchmark.py --only-mapping --repeats 5`;
|
||
它先检查源代码哈希,再重测 A/B/C,保留后面的已有算法实验,在报告中分别注明测量日期。
|
||
|
||
## 当前视频的范围
|
||
|
||
视频前半段保留 CPU/CUDA 与坐标计算复用的演进;后半段沿当前 `bench/slime-bench` 数据流讲解 Random 优化,不穿插坐标余数对或独立研究分支。
|
||
每一步说明为什么成立、减少哪部分工作,以及留下什么候选。
|
||
当前入口使用普通候选模型,可能漏掉依赖拒绝重抽的解;最终准确验证保证输出正确,不能补回漏掉的候选。
|
||
各项效果页引用冻结的同任务对照,并分别标明 kernel、搜索阶段和批次墙钟,章节与讲稿入口见 [视频工程](video/README.md)。
|
||
|
||
独立筛轴的教学实现、测速结果和视频章节已移除,历史结论保存在 [X/Z 筛轴试错报告](../research/XZ_FILTER_TRIAL_REPORT.md)。
|
||
|
||
后续优化的数学、实现状态和新基准均见 [统一教程](DOCUMENT.md),
|
||
不把历史 `BENCHMARK.md` 改写成未重新测量的当前性能报告。
|