170 lines
10 KiB
Markdown
170 lines
10 KiB
Markdown
# 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 上执行。
|