geopro/docs/superpowers/plans/poc-results-B.md

8.7 KiB
Raw Blame History

POC-B 实测结果gpr_poc headless 度量)

工具:tools/gpr_pocCLI构建产物 build/release/tools/gpr_poc/gpr_poc.exe。 执行机Windows 11MSVCVS18 Community+ NinjaRelease/O2。 日期2026-06-23。

整条地基链路: assembleGprSurvey → buildGprVolume → ChunkedVolumeStore::write → buildPyramid → WholeVolumeSource(load)


1. selftest合成极小数据—— PASS

命令:gpr_poc selftest

  • 构造 2 通道合成 surveysamples=8traces=12写临时 .iprb/.iprh/.ord 走完整 assembleGprSurvey → buildGprVolume → write(brick=4) → buildPyramid(1) → WholeVolumeSource
  • 断言ntraces/samples/channels、channelY 升序、GridSpec 2x2x8、建体维度、 金字塔层数==2、整卷维度一致、(0,0,0) 非 blank。
  • 结果:PASS(退出码 0

结论:除真实 .iprb 读入外,整条地基管线在合成数据上端到端跑通 (装配几何、建体量化、分块压缩落盘、金字塔降采样、整卷重组加载均正确)。


2. 真实数据D:\Downloads\明星路,线 001—— PASS实测

更新(任务 9b2026-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 <store> --levels 2
gpr_poc load  <store>

根因回顾off-by-onelastTrace+1 vs 真实道数)

readIprb 硬编码 traces = h.lastTrace + 1 并对文件字节做严格相等校验。 真实明星路每个通道文件恰好含 lastTrace 条道(少 1 道),逐通道实测:

通道 文件字节 samples LAST TRACE 旧期望(=samples·(lastTrace+1)·2) 实际道数(=bytes/(samples·2))
A01 74390810 821 45305 74392452 45305
A02 74394094 821 45307 74395736 45307
A12 74392452 821 45306 74394094 45306

规律一致:所有通道「实际道数 == LAST TRACE」。修复后 readIprb 不再用 lastTrace 决定道数装配按各通道道数最小值对齐min=45305

build 实测指标line 001, cellXY=0.2, cellZ=0.05, levels=2

指标
发现通道数 14
装配后 ntraces / samples / channels 45305 / 821 / 14
dx / dz 0.049084 / 0.00977756
GridSpecnx×ny×nz 11120 × 8 × 162
体素数 14,411,520
原始体积int16 28,823,040 B27.49 MB
落盘 data.bin含金字塔各级 15,317,628 B14.61 MB
压缩比(原始/落盘) 1.88×
装配耗时 12,551 ms
建体耗时 1,926 ms
落盘耗时 3,597 ms
金字塔耗时 3,923 ms
build 端到端墙钟 ≈22.6 s
峰值内存 4,975 MB

load 实测指标

指标
加载耗时 335 ms
整卷维度 11120 × 8 × 162
整卷字节 28,823,040 B27.49 MB
峰值内存 38 MB

无 OOM、无超时未调粗 cellXY 即一次通过。

峰值内存说明4.98 GB

峰值由装配阶段主导:同时持有 14 通道 BScan14×74 MB ≈ 1 GB int16

  • GprSurvey.valuesdouble14×45305×821×8 B ≈ 4.2 GB。 建体/落盘/加载本身很轻load 仅 38 MB。若后续要压内存可让 survey.values 改存 int16 或流式装配但当前规模单机可承受POC 不做此优化。

3. 深度/Z 尺度诊断结论(任务 9b

先前 §3 预估「nz=1、深度量级 8e-6 m」是在 SOIL VELOCITY 未正确换算时写下的 (当时按 100 m/s 计算。Task 1 已将 SOIL VELOCITY(头文件单位 m/µs×1e6 存为 m/s 本任务实测确认整条 Z 链路正确:

  • SAMPLES=821TIMEWINDOW=160.352 nsSOIL 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

结论assembler/GprGeometry/CLI specFromSurvey 的 Z 计算全部正确 无需改 CLI。先前的 nz=1 症状是 soilVelocity 换算缺失时代的遗留,现已不复存在。 CLI 的 specFromSurvey 用的是 survey.dz(来自 depthOfSample),未误用原始 100未漏乘。


4. 离屏 GPU 渲染基准(任务 9c2026-06-23

工具新增子命令:gpr_poc offscreen-smoke(闸门)、gpr_poc renderB <store> [--frames N]。 执行机 GPUNVIDIA GeForce RTX 3060 Laptop GPUOpenGL 4.5.0 NVIDIA 555.97,硬件加速 True。

4.1 闸门offscreen-smoke —— OK离屏 GL 可用)

命令:gpr_poc offscreen-smoke

  • 离屏 vtkRenderWindowSetOffScreenRendering(1)+SetShowWindow(false)256×256 → 加 cube actor → Render()GetRGBACharPixelData 读回。
  • 读回 65536 像素,非背景像素 28224cube 正确画出)。
  • GL vendor=NVIDIA Corporationrenderer=RTX 3060 Laptop GPU硬件加速 True。
  • 结论:离屏 GPU 渲染在本机可用,继续真实基准(非编造)。

4.2 基准数据line 001更细一档 cellXY=0.05

命令:gpr_poc build "D:\Downloads\明星路" --line 001 --cellXY 0.05 --cellZ 0.05 --out <store> --levels 1

指标
体维度nx×ny×nz 44476 × 29 × 162
体素数 208,948,248≈2.09 亿)
整卷字节int16进显存判据 417,896,496 B398.54 MB
data.bin含金字塔 199.43 MB压缩比 2.00×
build 峰值内存 4,830 MB装配阶段 double survey 主导,同 §2.4
整卷加载耗时renderB load ≈2.84.0 s
renderB 进程峰值内存 ≈509 MB(加载整卷 398 MB + 渲染管线)

无 build OOMcellXY=0.05 一次通过,未调粗。

4.3 renderB 实测指标 —— 关键发现:整卷体绘制不可行

命令:gpr_poc renderB <store> --frames 120

指标
离屏闸门复检 OK
体绘制 fps INVALID整卷超 3D 纹理上限)
├ raw_fps空纹理渲染不可信 295.6(仅作记录,非真实帧率)
├ SmartVolumeMapper 渲染模式 2 = GPURenderMode
└ vtkVolumeTexture 报错 Invalid texture dimensions [44476, 29, 162]
切片扫描 fps 54.6 fps120 帧沿 Z 扫整卷reslice+纹理)
整卷进显存 X=44476 > GL_MAX_3D_TEXTURE_SIZE=16384
降质重采样LowRes 否(未触发;是直接纹理维度超限失败,非显存不足降质)
GPU 显存NVX N/A(随包 VTK 安装未带 GLEW 头,无法直查 NVX_gpu_memory_info
但 GL 扩展列表确认该扩展存在,机器支持,仅本工具未链 GL loader
进程峰值内存 ≈509 MB

关键发现(务必看)

  1. 整卷体绘制在本机离屏下不可行:测线 001 的 X 维(沿测线方向)= 44476 远超本机 OpenGL GL_MAX_3D_TEXTURE_SIZE = 16384vtkSmartVolumeMapper 走 GPU 路径mode=2但底层 vtkVolumeTexture 无法将整卷上传为单张 3D 纹理Invalid texture dimensions。此时 Render() 实际未绘出体数据, 故所谓 295 fps 是空纹理渲染的假帧率,已如实标 INVALID绝不上报为体绘制性能
  2. 切片扫描真实流畅:切片走 vtkImageReslice 输出 2D 切面 + 2D 纹理着色, 不受 3D 纹理维度上限约束,实测 54.6 fps ≥ 30fps 目标,整卷切片交互流畅。
  3. 进显存判据:整卷 398 MB 远小于 GPU 显存RTX 3060 6GB显存容量不是瓶颈 真正的瓶颈是单轴纹理维度上限16384,而非显存字节数。

结论

  • 切片 本机离屏下整卷切片 ≥30fps54.6fps),交互流畅,满足目标。
  • 整卷体绘制 在「整卷成单张 3D 纹理」的朴素路径下不可行—— 长测线 X 维超 GL 单轴上限。这正是 Task 12核外 / 分块 LOD / 体纹理分区 vtkOpenGLGPUVolumeRayCastMapper::SetPartitions 必须解决的问题: 要么沿 X 分区/分块上传,要么按视相机做 LOD 工作集。本任务9c按约束不做核外 仅如实记录此限制作为 Task 12 的硬性依据。
  • 该限制与显存容量无关,是 OpenGL 纹理维度硬上限;任何「整卷一次性 3D 纹理」方案 对长测线都会撞同一面墙。