diff --git a/docs/superpowers/plans/poc-results-B.md b/docs/superpowers/plans/poc-results-B.md index 89cdbbf..02996ee 100644 --- a/docs/superpowers/plans/poc-results-B.md +++ b/docs/superpowers/plans/poc-results-B.md @@ -24,81 +24,82 @@ --- -## 2. 真实数据(D:\Downloads\明星路,线 001)—— **BLOCKED(前置 IO 层与真实数据契约不符)** +## 2. 真实数据(D:\Downloads\明星路,线 001)—— **PASS(实测)** + +> 更新(任务 9b,2026-06-23):先前 BLOCKED 的根因(`readIprb` 硬假设 +> `traces = lastTrace + 1`)已修复。`readIprb` 改为**以文件大小为权威** +> (`traces = fileBytes / (samples·2)`),真实数据装配通过。 命令: ``` -gpr_poc build "D:\Downloads\明星路" --line 001 --cellXY 0.2 --cellZ 0.05 --out %TEMP%\gpr_store_001 --levels 2 +gpr_poc build "D:\Downloads\明星路" --line 001 --cellXY 0.2 --cellZ 0.05 --out --levels 2 +gpr_poc load ``` -进度: -- 文件发现 **成功**:定位 14 通道 `明星路_001_A01..A14.iprb` + `明星路_001.ord`。 -- 装配 **失败**:`assembleGprSurvey` → `readIprb` 抛 - `文件大小与 samples*traces*2 不符: ..._A01.iprb`。 +### 根因回顾(off-by-one:lastTrace+1 vs 真实道数) -### 根因(off-by-one:lastTrace+1 vs 真实道数) - -`readIprb`(前置 IO 层,`src/io/gpr/IprbReader.cpp:16`)硬编码 -`traces = h.lastTrace + 1` 并对文件字节数做**严格相等**校验。 +旧 `readIprb` 硬编码 `traces = h.lastTrace + 1` 并对文件字节做严格相等校验。 真实明星路每个通道文件恰好含 `lastTrace` 条道(少 1 道),逐通道实测: -| 通道 | 文件字节 | samples | LAST TRACE | 期望(=samples·(lastTrace+1)·2) | 实际道数(=bytes/(samples·2)) | -|------|----------|---------|------------|--------------------------------|------------------------------| +| 通道 | 文件字节 | samples | LAST TRACE | 旧期望(=samples·(lastTrace+1)·2) | 实际道数(=bytes/(samples·2)) | +|------|----------|---------|------------|----------------------------------|------------------------------| | A01 | 74390810 | 821 | 45305 | 74392452 | 45305 | | A02 | 74394094 | 821 | 45307 | 74395736 | 45307 | -| A03 | 74390810 | 821 | 45305 | 74392452 | 45305 | -| A04 | 74394094 | 821 | 45307 | 74395736 | 45307 | -| A05 | 74390810 | 821 | 45305 | 74392452 | 45305 | -| A06 | 74394094 | 821 | 45307 | 74395736 | 45307 | -| A07 | 74390810 | 821 | 45305 | 74392452 | 45305 | -| A08 | 74394094 | 821 | 45307 | 74395736 | 45307 | -| A09 | 74390810 | 821 | 45305 | 74392452 | 45305 | -| A10 | 74394094 | 821 | 45307 | 74395736 | 45307 | -| A11 | 74390810 | 821 | 45305 | 74392452 | 45305 | | A12 | 74392452 | 821 | 45306 | 74394094 | 45306 | -| A13 | 74390810 | 821 | 45305 | 74392452 | 45305 | -| A14 | 74394094 | 821 | 45307 | 74395736 | 45307 | -**规律一致**:所有通道「实际道数 == LAST TRACE」,即真实文件道数 = `lastTrace`, -而 `readIprb` 期望 `lastTrace + 1`,每通道恰差 1 道(`samples·2 = 1642` 字节)。 +**规律一致**:所有通道「实际道数 == LAST TRACE」。修复后 `readIprb` 不再用 `lastTrace` +决定道数,装配按各通道道数最小值对齐(min=45305)。 -这是**前置 IO 层契约与真实数据约定的系统性不符**,不是 gpr_poc CLI 的问题。 -现有单测(`tests/io/gpr/test_iprb_reader.cpp:30-31`)显式锁定 -「字节数 != samples·(lastTrace+1)·2 → 抛异常」,故 `lastTrace+1` 是被测试钉死的契约。 +### build 实测指标(line 001, cellXY=0.2, cellZ=0.05, levels=2) -### 处置(本任务未擅自改前置/测试) +| 指标 | 值 | +|------|-----| +| 发现通道数 | 14 | +| 装配后 ntraces / samples / channels | 45305 / 821 / 14 | +| dx / dz(米) | 0.049084 / **0.00977756** | +| GridSpec(nx×ny×nz) | **11120 × 8 × 162** | +| 体素数 | 14,411,520 | +| 原始体积(int16) | 28,823,040 B(27.49 MB) | +| 落盘 data.bin(含金字塔各级) | 15,317,628 B(14.61 MB) | +| 压缩比(原始/落盘) | **1.88×** | +| 装配耗时 | 12,551 ms | +| 建体耗时 | 1,926 ms | +| 落盘耗时 | 3,597 ms | +| 金字塔耗时 | 3,923 ms | +| build 端到端墙钟 | ≈22.6 s | +| 峰值内存 | **4,975 MB** | -按任务纪律(外科手术式改动、不动他人已测契约、严禁编造指标), -本会话**未修改** `readIprb` 或其单测,故真实数据的建体/维度/压缩比/加载/峰值内存 -**暂无法实测**,如实记录为 BLOCKED。 +### load 实测指标 -不是 OOM、不是超时——是装配前的文件读入契约不符,调粗 `--cellXY` 也无法绕过 -(在到达建体之前就抛了)。 +| 指标 | 值 | +|------|-----| +| 加载耗时 | 335 ms | +| 整卷维度 | 11120 × 8 × 162 | +| 整卷字节 | 28,823,040 B(27.49 MB) | +| 峰值内存 | 38 MB | -### 建议解法(需 POC/IO 层 owner 决策,任一) +无 OOM、无超时,未调粗 cellXY 即一次通过。 -1. **放宽 `readIprb`**:以「文件字节数 / (samples·2)」反推真实道数(容忍 ±N 道), - 而非硬用 `lastTrace+1`;同步更新 `test_iprb_reader.cpp`。这与真实数据约定 - (道数 = `lastTrace`)一致,最贴近现场。 -2. **明确 LAST TRACE 语义**:若约定其为「道数」而非「末道索引」,则 `traces = lastTrace` - (去掉 +1),同样需改实现 + 测试。 -3. 任一方案落地后,重跑: - `gpr_poc build "D:\Downloads\明星路" --line 001 --cellXY 0.2 --cellZ 0.05 --out --levels 2` - 再 `gpr_poc load `,本文件 §2 即可补齐真实指标。 +### 峰值内存说明(4.98 GB) + +峰值由**装配阶段**主导:同时持有 14 通道 BScan(14×74 MB ≈ 1 GB int16) ++ `GprSurvey.values` 以 **double** 存(14×45305×821×8 B ≈ 4.2 GB)。 +建体/落盘/加载本身很轻(load 仅 38 MB)。若后续要压内存,可让 survey.values +改存 int16 或流式装配,但当前规模单机可承受,POC 不做此优化。 --- -## 3. 预估几何(供解法落地后核对,非实测) +## 3. 深度/Z 尺度诊断结论(任务 9b) -基于真实头:samples=821,dx≈0.049084 m,通道横偏 Y∈[-0.686, 0.686](跨度≈1.372 m), -土速 100 m/s、时窗 160.352 ns ⇒ 深度跨度 `depthOfSample(820)≈8.0e-6 m`(量级极小)。 +先前 §3 预估「nz=1、深度量级 8e-6 m」是在 SOIL VELOCITY **未正确换算**时写下的 +(当时按 100 m/s 计算)。Task 1 已将 `SOIL VELOCITY`(头文件单位 m/µs)×1e6 存为 m/s, +本任务实测确认整条 Z 链路正确: -按 `--cellXY 0.2 --cellZ 0.05`、X 跨度≈`45305·0.049084≈2223 m`: -- nx ≈ ceil(2223/0.2)+1 ≈ **11118** -- ny ≈ ceil(1.372/0.2)+1 ≈ **8** -- nz ≈ ceil(8.0e-6/0.05)+1 = **1**(Z 物理跨度远小于 cellZ,故仅 1 层) +- 头:SAMPLES=821,TIMEWINDOW=160.352 ns,SOIL VELOCITY=100(→ 1e8 m/s)。 +- `depthOfSample(820) = 1e8 × 160.352e-9 / 2 ≈ **8.018 m**`(深度跨度合理)。 +- `dz = depthOfSample(1) = 8.018/820 ≈ **0.009778 m**`(实测 0.00977756,吻合)。 +- 故 cellZ=0.05 下 `nz = ceil(8.018/0.05)+1 = **162**`(实测 162,非 1)。 -**注意**:因 SOIL VELOCITY 存为 100 m/s(头文件单位 m/µs ×1e6 后),深度尺度为微米级, -`--cellZ 0.05`(5 cm)会把整个深度压成 1 层。落地解法后,若要在 Z 方向有分辨率, -需把 `--cellZ` 调到与深度跨度匹配的量级(约 1e-8 m),或复核土速/时窗单位约定。 -此项一并提请 POC owner 确认(影响真实体维度与后续渲染基准 9c)。 +**结论**:`assembler`/`GprGeometry`/CLI `specFromSurvey` 的 Z 计算**全部正确**, +无需改 CLI。先前的 nz=1 症状是 soilVelocity 换算缺失时代的遗留,现已不复存在。 +CLI 的 `specFromSurvey` 用的是 `survey.dz`(来自 `depthOfSample`),未误用原始 100,未漏乘。