slime/bench/README.md

170 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# slime-bench:普通分支全种子搜索基准
指定中心区块、曼哈顿半径和自定义图案(或实心 `n×n`),搜索范围内每个锚点的全部有效种子,输出 JSON 结果及计时。支持 NVIDIA CUDA 单卡、多卡。
## 本地编译与运行
需要 Linux/WSL、CUDA Toolkit(nvcc,推荐 12 或以上)、支持 C++17 的主机编译器。运行时需要 NVIDIA 驱动。项目根目录执行:
```sh
make -C bench
mkdir -p artifacts
./bench/bin/slime-bench --list-devices
./bench/bin/slime-bench --x 0 --z 0 --radius 64 --size 5 \
--devices 0 --repeat 3 --output artifacts/local-r64-n5.json
```
默认编译 `sm_86` 并附带 PTX,适合本机 RTX 3060 Laptop。换架构时用 `-B` 强制重建;仅改变 Make 变量不会使已有文件自动过期。
## 已验证实例:5×5 爱心
种子 **`22428888508636`**,左上角区块 **`(-5,-147)`**(方块原点 `(-80,-2352)`)。每格一个区块,向右为 `+X`、向下为 `+Z`;16 格 `#` 必须是史莱姆,9 格 `.` 必须不是:
```text
.#.#.
#####
#####
.###.
..#..
```
```sh
./bench/bin/slime-bench --radius 256 \
--pattern-file bench/patterns/heart-5x5.txt \
--position-batch 256 --max-results 1000
# 单点复查,收集全部普通分支匹配:应得到 1,181 个种子
./bench/bin/slime-bench --x -5 --z -147 --radius 0 \
--pattern-file bench/patterns/heart-5x5.txt --max-results 2000
```
RTX 3060 Laptop 实测:131,585 个锚点,普通分支共找到 1,456 个种子/位置匹配,扫描约 2.439 秒(含设备初始化的端到端约 2.620 秒)。保存的 1,000 个搜索样本,以及单点复查的全部 1,181 个种子,都通过独立 Python 实现的 Java 整数回绕及 `Random.nextInt(10)` 精确逐格验证。已知种子及计时见 [results/heart-5x5-example.json](results/heart-5x5-example.json)。GPU 回归检查单点计数、已知种子及全部样本,搜索计数不包含拒绝重抽补扫。
## 自定义图案:6×6 苦力怕
`--pattern` 接受 `/` 分隔的行,或用 `--pattern-file` 读取每行一排的文本文件。`#` 必须是史莱姆区块,`.` 必须不是,`?` 不限制。支持非正方形,宽、高分别为 1~64,至少含一个 `#`;不能与 `--size` 同时指定。不自动旋转或镜像。
内置示例 [patterns/creeper-6x6.txt](patterns/creeper-6x6.txt) 将脸部像素设为史莱姆:
```text
##..##
##..##
..##..
.####.
.####.
.#..#.
```
```sh
./bench/bin/slime-bench --radius 512 \
--pattern-file bench/patterns/creeper-6x6.txt \
--position-batch 128 --max-results 100 --output artifacts/creeper.json
# 也可直接输入;必须使用引号保护 #、? 等字符
./bench/bin/slime-bench --radius 512 \
--pattern '##..##/##..##/..##../.####./.####./.#..#.' --max-results 100
```
目标是上面的正色模板:眼睛、鼻子和嘴巴为史莱姆区块,背景必须不是。已检查原点半径 2048、中心 `(51069,419124)` 半径 1024、32 个分散区域各半径 256、另外 128 个分散区域各半径 512;还筛选了 65,536 个坐标,选出低位候选最多的 64 个坐标类,检查这些类在世界边界内的全部 104,538 个实际位置。累计 82,047,228 次锚点检查仍未命中(不同路线可能重叠,见[搜索记录](results/creeper-6x6-search.json))。这不证明正色不存在;不能用反色图案作为该目标的搜索结果。
每行从左到右沿 `+X`,从上到下沿 `+Z`。返回坐标仍是矩形左上角,即使该格是 `.` 或 `?`。将 `.` 改为 `?` 可只要求轮廓、允许背景出现额外史莱姆区块。JSON 包含原始 `pattern` 行、宽高及两类约束数;自定义输入的 `square_size` 为 `null`。
筛选和区间求解只使用 `#` 格,随后精确核对所有 `.` 格;`?` 不参与计算。稀疏图案的候选可能很多,搜索时间不能直接套用实心方阵的基准。搜索口径仍为普通分支,不包含拒绝重抽补扫。
## H100 服务器
将仓库内的 `bench/` 和 `include/` 一起复制到服务器,保持相对路径;CLI 依赖 `include/slime/` 中的共用头文件。
```sh
make -C bench -B CUDA_ARCH=90
mkdir -p artifacts
./bench/bin/slime-bench --list-devices
# 先测单张 H100,和本地使用相同范围、尺寸及批大小。
./bench/bin/slime-bench --x 0 --z 0 --radius 64 --size 5 \
--devices 0 --repeat 3 --output artifacts/h100-one-r64-n5.json
# 再测全部可见 GPU;八卡机器即可使用八张卡。
./bench/bin/slime-bench --x 0 --z 0 --radius 64 --size 5 \
--devices all --repeat 3 --output artifacts/h100-all-r64-n5.json
```
也可以指定 `--devices 0,1,2,3,4,5,6,7`。编号遵循 `CUDA_VISIBLE_DEVICES` 的可见编号。重复/不存在的设备编号会报错。多卡以动态位置批次分配任务,完整覆盖范围一次,各卡独立缓存类根,结果总数合并;所有 GPU 初始化完成后一起开始计时。实际八卡性能尚未在本机验证。
半径 64 包含 8,321 个锚点,适合先验证环境。正式比较可以在两台机器上使用下面同一套较长参数(半径 512,共 525,313 个锚点):
```sh
./bench/bin/slime-bench --x 0 --z 0 --radius 512 --size 5 \
--position-batch 128 --devices all --repeat 3 --output artifacts/benchmark-r512-n5.json
```
若八卡上仍耗时太短,可同时增大半径。`--repeat 3` 是完整扫描三遍,不是只跑三次 kernel。默认无额外隐藏预热;第一轮包含首次 kernel/JIT 开销,报告保留每一轮数据。
## 范围与搜索口径
```text
abs(anchor_x - x) + abs(anchor_z - z) <= radius
锚点数量 = 1 + 2*radius*(radius+1)
```
- `x,z,radius` 的单位都是区块,不是方块。
- 锚点是图案最小 X、最小 Z 的角;图案沿 `+X,+Z` 延伸。自定义图案的锚点是外接矩形的角。
- 半径限制锚点,图案允许超出菱形范围。
- 不自动按世界边界裁剪;锚点和整块图案须在 int32 坐标范围内,否则报错。
- `--size` 支持 1~6,默认 5。小尺寸匹配种子极多,全种子计数也可能耗时很久,不能用 1×1 推断 5×5 性能。
- 遍历所有有效低 48 位种子的**普通候选分支**。沿用低位筛选、16 候选组 mask、区间求交、精确 Java 验证,**不包含拒绝重抽补扫**。
- 返回的种子是 `[0,2^48)` 内的有效代表;不重复枚举高 16 位等价的 64 位世界种子。
这是范围基准 CLI,不提供全世界长跑的断点续跑。Ctrl+C 可终止,未完成扫描不会输出成功报告。
## 参数及输出
```sh
./bench/bin/slime-bench --help
# 不使用 GPU,只检查输入范围
./bench/bin/slime-bench --x 51069 --z 419124 --radius 2 --size 5 --dry-run
# 已知位置验证:应该得到 24 个种子
./bench/bin/slime-bench --x 51069 --z 419124 --radius 0 --size 5 \
--max-results 100 --repeat 3 --output artifacts/known.json
```
本文示例均从项目根目录运行,输出前请先执行 `mkdir -p artifacts`。日常跑分写入已忽略的 `artifacts/`;`results/` 只保存需要长期引用的基准样例。
JSON 输出到 stdout,状态/约每 5 秒进度输出到 stderr;`--output` 同时保存 JSON,已有文件会报错以免覆盖。默认只计数;`--max-results N` 最多保留 N 个示例三元组 `[seed48,chunk_x,chunk_z]`,**不提前停止扫描**。示例顺序受 GPU 调度影响,不能按示例子集或其顺序对比性能/正确性。`sample_truncated` 表示有命中没有保存在示例中,`matches` 始终是完整计数;整数计数溢出会失败。
主要计时字段:
| 字段 | 含义 |
|---|---|
| `rounds[].elapsed_ms` | 本轮启动工作线程、设备初始化/分配、完整扫描及资源清理的墙钟时间 |
| `rounds[].scan_wall_ms` | 所有 GPU 就绪后,从最早开始扫描到最后完成的墙钟时间,含本轮分组、根生成、传输、展开、搜索、结果回传 |
| `median_scan_wall_ms` | 各轮 `scan_wall_ms` 的中位数,适合本地与服务器比较 |
| `rounds[].anchors_per_second` | 实际锚点数 / 扫描墙钟秒数 |
| `gpus[].root_stage_ms` | 该 GPU 工作线程的代表类构造、根筛选、回传、整理及缓存耗时 |
| `gpus[].search_stage_ms` | 该线程的根任务上传、公共项准备、成组搜索和命中回传耗时 |
| `gpus[].scan_ms` | 该线程完整扫描耗时;还包含以上两阶段外的调度、具体位置构造等工作 |
多卡阶段时间相互重叠,不要把八卡 `scan_ms` 相加当作完成时间。比较相同的中心、半径、尺寸和批大小;位置根分布差异很大,单个已知命中点不适合代表全世界平均吞吐。
可调批参数:
- `--position-batch 32`:每个动态任务最多 32 个锚点,支持 1~256。
- `--job-batch 2048`:每次搜索最多 2048 个低位根任务,支持 1~65536。
- `--cache-classes 4096`:每卡缓存的坐标类数量,0 禁用;另限制最多约 1,048,576 个缓存根,FIFO 淘汰。每轮清空缓存,避免重复测量只跑缓存命中。
按坐标类归一化并只构造有根类的具体位置。此 CLI 使用有限缓存、按曼哈顿行顺序调度;不是此前设想的全世界按类遍历计划。小半径下通常没有重复类,所以测到的根生成费用是真实费用,不会按假设将其省略。半径范围的实测吞吐不能直接替代此前约 50 天的全世界类复用搜索阶段外推。
## 检查
```sh
make -C bench test # 无需 GPU:范围、输入、可变尺寸数学对照
make -C bench test-gpu # 需要 GPU:实际搜索与文件输出验证
```
验证内容包括:自定义图案解析和边界、稀疏图案高位枚举对照、带忽略格及非史莱姆格的 GPU 结果与独立 Java 算法筛选对照,以及半径 0~64 的完整菱形枚举,较大半径抽样,1~6 中多个尺寸的组 mask 对照,已知 24 个命中,小根批分拆一致性,4×4 的全部 422 个示例经独立 Java 算法验证,6×6 的已知种子子集对照,以及半径 2 批量结果与全部 13 个位置分别搜索的完整列表一致。
本机实测:RTX 3060 Laptop,中心 `(0,0)`,半径 512,5×5,`--position-batch 128 --repeat 3`。525,313 个锚点,三轮均有 368,935 个低位根任务、0 个命中,扫描墙钟中位数约 **3.990 秒**。原始 JSON 在 [results/local-r512-n5.json](results/local-r512-n5.json)。另有半径 64 的快速环境验证记录;其批大小为默认 32,与上述正式样例不同。
H100 的 `sm_90` 原生代码和 PTX 已在本机交叉编译通过,尚未在 H100 或八张物理 GPU 上执行。