Add verified heart pattern example
This commit is contained in:
parent
7952207735
commit
f71985c0c3
5 changed files with 97 additions and 1 deletions
|
|
@ -8,7 +8,7 @@ make bench
|
|||
--position-batch 128 --devices all --repeat 3
|
||||
```
|
||||
|
||||
自定义图案用 `--pattern` 或 `--pattern-file`,支持史莱姆、非史莱姆和忽略格;见 [6×6 苦力怕示例](bench/README.md#自定义图案6x6-苦力怕)。
|
||||
自定义图案用 `--pattern` 或 `--pattern-file`,支持史莱姆、非史莱姆和忽略格;见 [已验证的 5×5 爱心](bench/README.md#已验证实例5x5-爱心)及 [6×6 苦力怕示例](bench/README.md#自定义图案6x6-苦力怕)。
|
||||
|
||||
H100 编译:`make -C bench -B CUDA_ARCH=90`。需要 CUDA Toolkit 和 C++17 编译器。普通分支不包含拒绝重抽补扫,不能将它的结果声明为严格完整目录;参数和计时口径见 [CLI 使用说明](bench/README.md)。
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,30 @@ mkdir -p artifacts
|
|||
|
||||
默认编译 `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` 同时指定。不自动旋转或镜像。
|
||||
|
|
|
|||
5
bench/patterns/heart-5x5.txt
Normal file
5
bench/patterns/heart-5x5.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
.#.#.
|
||||
#####
|
||||
#####
|
||||
.###.
|
||||
..#..
|
||||
52
bench/results/heart-5x5-example.json
Normal file
52
bench/results/heart-5x5-example.json
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
"pattern": [
|
||||
".#.#.",
|
||||
"#####",
|
||||
"#####",
|
||||
".###.",
|
||||
"..#.."
|
||||
],
|
||||
"seed48": 22428888508636,
|
||||
"chunk_x": -5,
|
||||
"chunk_z": -147,
|
||||
"block_origin": [
|
||||
-80,
|
||||
-2352
|
||||
],
|
||||
"verified_rows": [
|
||||
".#.#.",
|
||||
"#####",
|
||||
"#####",
|
||||
".###.",
|
||||
"..#.."
|
||||
],
|
||||
"verification": {
|
||||
"method": "independent Python implementation of Java int overflow and Random.nextInt(10) rejection loop",
|
||||
"verified_search_sample_count": 1000,
|
||||
"verified_single_anchor_count": 1181,
|
||||
"slime_cells": 16,
|
||||
"non_slime_cells": 9
|
||||
},
|
||||
"search": {
|
||||
"center": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"radius_chunks": 256,
|
||||
"anchors": 131585,
|
||||
"matches": 1456,
|
||||
"scan_wall_ms": 2438.534811,
|
||||
"elapsed_ms": 2619.994137,
|
||||
"gpu": "NVIDIA GeForce RTX 3060 Laptop GPU",
|
||||
"rejection_tail_included": false
|
||||
},
|
||||
"single_anchor": {
|
||||
"matches": 1181,
|
||||
"root_jobs": 405
|
||||
},
|
||||
"source_sha256": {
|
||||
"bench/slime_bench.cu": "3c70cbe2e5babc3e737199fb5e62b78ea9c5daadc0020af77292c2d59516259e",
|
||||
"include/slime/solver_core.hpp": "feb1200518716b4d796fb60f60a83b6b798155bbd4e795531793181a5c7f9eba",
|
||||
"include/slime/upper_interval.hpp": "af3fddf7705295d91ffd6e2190f542004a3ecff847fce9d4c9b13125bdbdc2d5"
|
||||
}
|
||||
}
|
||||
|
|
@ -40,8 +40,23 @@ def main():
|
|||
with tempfile.TemporaryDirectory() as tmp:
|
||||
path=Path(tmp)/'pattern.txt';path.write_bytes(b'?##.\r\n#..?\r\n..#?\r\n')
|
||||
assert run('--radius',0,'--pattern-file',path,'--dry-run')['pattern']==pattern.split('/')
|
||||
heart_fixture=json.loads((HERE/'results/heart-5x5-example.json').read_text())
|
||||
assert (HERE/'patterns/heart-5x5.txt').read_text().splitlines()==heart_fixture['pattern']
|
||||
assert all(slime(heart_fixture['seed48'],heart_fixture['chunk_x']+dx,heart_fixture['chunk_z']+dz)==(ch=='#')
|
||||
for dz,row in enumerate(heart_fixture['pattern']) for dx,ch in enumerate(row))
|
||||
summary={'cli_scope_and_errors':True,'pattern_inputs':True}
|
||||
if args.gpu:
|
||||
heart_poc=run('--x',heart_fixture['chunk_x'],'--z',heart_fixture['chunk_z'],'--radius',0,
|
||||
'--pattern-file',HERE/'patterns/heart-5x5.txt','--max-results',2000)
|
||||
heart_hits=heart_poc['rounds'][0]
|
||||
assert heart_hits['matches']==heart_fixture['single_anchor']['matches']
|
||||
assert heart_hits['root_jobs']==heart_fixture['single_anchor']['root_jobs']
|
||||
assert not heart_hits['sample_truncated'] and len(heart_hits['sample'])==heart_hits['matches']
|
||||
assert len(set(map(tuple,heart_hits['sample'])))==heart_hits['matches']
|
||||
assert [heart_fixture['seed48'],heart_fixture['chunk_x'],heart_fixture['chunk_z']] in heart_hits['sample']
|
||||
for seed,x,z in heart_hits['sample']:
|
||||
assert all(slime(seed,x+dx,z+dz)==(ch=='#') for dz,row in enumerate(heart_fixture['pattern']) for dx,ch in enumerate(row))
|
||||
summary['heart_pattern_verified_matches']=heart_hits['matches']
|
||||
# A mixed-mask regression fixture; this is not the target creeper pattern.
|
||||
fixture=json.loads((HERE/'testdata/mixed-mask-regression.json').read_text())
|
||||
face=run('--x',fixture['chunk_x'],'--z',fixture['chunk_z'],'--radius',0,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue