docs: add teaching examples and video project

This commit is contained in:
Yaossg 2026-10-11 12:29:28 +08:00
parent e93bc20b0a
commit 7a06f94577
42 changed files with 8022 additions and 0 deletions

145
show/README.md Normal file
View file

@ -0,0 +1,145 @@
# 史莱姆区块搜索:逐步演示
这里保存视频/博客草稿、按步骤编号的代码,以及本次实测结果。
演示代码在本目录,研究实现位于 `research/`。草稿见
[POPULAR_SCIENCE_OUTLINE.md](POPULAR_SCIENCE_OUTLINE.md)。
先读 [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 轴项 |
| 性质探索 | [RANDOM_PROPERTIES.md](RANDOM_PROPERTIES.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 结束。随后读 [RANDOM_PROPERTIES.md](RANDOM_PROPERTIES.md),
探索随机数的状态空间、低位依赖和模运算结构,再引出 07–08 的候选生成与解析求解。
这部分用推导和例子说明性质,不把 XOR 的等价改写列作计时优化。
07、08 完整流程是从对应 `research/` 实现提取的教学快照,文件头注明来源,
继续共享 `../research/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,保留后面的已有算法实验,在报告中分别注明测量日期。
## 视频里必须交代的边界
- 固定坐标线程与按 seed 线程是转置关系,哪种快取决于任务规模与循环中的算术复用。展平实现移至 `experiments/`,不属于这一阶段。
- 低 48 位不是新加入的剪枝:JavaRandom 从第一版起就只有 48 位状态。高 16 位等价性是一条性质,不是额外实测加速比。
- 07–08 的全局生成器仍用首次输出候选模型,可能漏掉依赖拒绝后重抽的解;最终准确验证不能补回漏掉的候选。
- 潜在笛卡尔积规模不是实际访问次数。收益不能跨任务相乘,全 seed × 全世界目录仍未解决。
- FFT 等失败方案的代码和数据仍在 `research` 归档,见草稿中的链接;本目录实测保留方案。
可直接用于叙事的结果应从本次报告取值,草稿里原有的研究数字作为历史记录保留。
独立筛轴的教学实现、测速结果和视频章节已移除,历史结论保存在 [X/Z 筛轴试错报告](../research/XZ_FILTER_TRIAL_REPORT.md)。