Add a bounded per-chunk center-tile selector to the real-event replay prototype and retain the paired timing, mixed-boundary, CPU, HIP, and sandbox-failure evidence.
16 KiB
HIP PSF 有界真实事件回放与像素归约实验(2026-09-07)
结论与交付
已实施原计划的有界捕获/回放、16×16 和 32×32 按像素归约原型、独立 CPU producer
诊断及正确性回归。原型保留在测试程序中,未替换生产 HIP 路径。
实现于 2026-09-11 提交为 7f5ec1a;以下日志和 hash 保留 2026-09-07 测量时的状态。
RX 9070 上,65,536 个真实银心视场事件的累积回放中位数从 104.107 ms 降至 69.823 ms(16×16,约 1.49×)。含公共 GPU 初始化为 137.111 → 102.323 ms(约 1.34×)。 但同等贡献的分散对照中,16×16 从 85.302 ms 退化至 104.389 ms;32×32 为 79.899 ms。 强放大样本的 32×32 结果波动区间与 atomic 重叠,不能确认稳定收益。因此尚不足以选择 一个通用生产默认算法;后续集成应先考虑分布选择及生产流式 producer 的端到端对照。 没有运行完整全天渲染,也没有推断新的全天加速比。
2026-09-11 自适应选择后续实验
在提交 11e703e33dffb1ff168ba11dd922e68b448116b9 之上增加了仅用于回放的
adaptive 模式,production sink 仍未改变。选择器逐个 16,384-event chunk 扫描
32×32 中心 tile 占用;chunk 至少有 8,192 events、且平均每个占用中心 tile 至少
32 events 时选择 tile16,否则选择现有 atomic。该阈值是基于本页固定输入提出的实验
假设,不是跨场景或跨设备参数。
选择扫描不构建 support 引用,四个样本的中位成本为 0.037--0.455 ms。tile 路径使用 独立的有界 event device buffer,不复用 production 双 staging slot,因此同一 stream 内 可以按 chunk 混合 atomic/tile;mixed fixture 实际覆盖 2 个 tile chunk、1 个 atomic chunk 和中途 direct fallback。所有额外 scratch 仍在 replay sink 创建时一次分配,未进入 renderer。
同一新 binary(SHA256
121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151)串行运行,
每项三次;表中为包含选择、分桶、上传、kernel、合并、下载和清理的 replay_wall
中位数:
| 65,536-event 输入 | paired atomic | paired tile16 | adaptive | adaptive 选择 |
|---|---|---|---|---|
| 银心密集 | 95.018 ms | 67.354 ms | 67.834 ms | 0.177 ms |
| 同贡献分散 | 78.203 ms | 99.693 ms | 80.092 ms | 0.455 ms |
自适应路径在密集输入相对 paired atomic 快约 1.40×,距固定 tile16 中位数 0.7%;在分散 输入保留 atomic,距其 paired 中位数 2.4%。另外两个真实输入的自适应中位数为强放大 21.617 ms、普通区域 18.347 ms,分别选择 1/1 tile chunk。银心选择 4/4 tile chunks, 分散对照选择 4/4 atomic chunks。此结果支持继续研究 production 流式集成,但尚未包含 OpenMP producer 与 sink 锁竞争,也没有授权用本回放结果宣称完整全天加速。
全部 adaptive/mixed 检查通过原有 finite、double HDR 和 RGB/Y 通量阈值;最坏
max_abs=5.96856e-11、max_rel=5.95958e-13、RGB 通量相对差
<=2.83233e-14、Y <=1.15036e-14。make -j1 test 与 production HIP primitive
也通过。第一次在受限沙箱内运行明确失败为 no ROCm-capable device is detected,随后只在
获准的主机 GPU 环境执行;失败记录保留,没有删除或覆盖。
原始证据:
- 构建:adaptive_build_host.log;
- adaptive 三次:
adaptive_{center_65536,dispersed_65536,lensed_16384,ordinary_12765}_host_{0,1,2}.log; - paired 基线:
paired_{center,dispersed}_{atomic,16}_{0,1,2}.log; - mixed、CPU 与 HIP 回归:
adaptive_boundary_mixed_host_0.log、adaptive_cpu_regression.log、adaptive_hip_primitive_host.log; - 受限环境失败:
adaptive_center_65536_0.log。
每份日志均保留完整命令、45/90 s timeout、Git hash、binary hash(适用时)、程序原始输出、 process wall 和 exit status。所有性能进程均由现有独占 runner 串行执行,未与其他 renderer 或 profiler 并发。
实现入口:
- capture_psf.c:调用真实 producer 的测试专用 consumer,捕获或诊断,不生成 HDR。
- replay_psf.hip:CPU double reference、现有 atomic、两种 tile 原型。
- make_psf_fixture.c:单独标记的合成边界/热点/wing fixture。
- test_psf_capture.py:边界限制、分类、串行/并行/索引摘要、拒绝覆盖验证。
- 全部原始证据与索引。
环境与测量纪律
Git 基线 5eccc31c99db96de2a0597babf2fd4c2149e91e7,测量时在此基础上有未提交修改。
没有覆盖用户已有的计划修改。生产 src/hip_psf.hip 未改;src/frame.c 的诊断钩子
仅在 standalone 测试编译时启用。每次直接执行的 binary SHA256 在相应日志中;
源码、binary、lens map hash、
宿主环境、
构建命令与 build*.log 保存完整配置。
Release / C -O2 -march=native / HIP -O2 --offload-arch=gfx1201,HIP 7.2,RX 9070。
回放 CPU reference 为串行;diagnostic 最多 16 workers;混合 renderer fixture 为 4 workers。
各进程重建相同 immutable cache:FWHM=2.7、beta=4.5、tail=1e-8,64 phase intervals、
47px cache radius。没有清除文件系统 page cache;输入是重复读取的固定小文件。
所有测试进程串行,回放超时 45 s、缩小 renderer 超时 60 s;未出现测试超时。
早期 v3_* 期间部分编译活动重叠,全部 v3_* 仅用作探索/正确性证据。
下表只用构建和回归结束后的 final_* 三次独立复测,不引用受构建干扰的时间。
run.py 记录命令、原始 stdout/stderr、退出码和进程 wall,失败立即停止,限时进程被 kill
后会 wait/reap;独占锁及启动前的进程检查防止本套工具重叠运行。
固定输入、选择规则与实际覆盖
使用已有 3840×2160 Schwarzschild lens map,不重新 tracing/refine。只读取两个指定 catalog tile 的均匀 8,192 行子集,见 输入 manifest 和 重建脚本。没有遍历完整全天 catalog。
捕获器限制 CSV≤8 MiB、stars≤32,768、lens map≤64 MiB/单帧、triangle 范围≤131,072、
缓存事件≤65,536、分类总数≤131,072。按 triangle ID、原 catalog 顺序捕获,保留所有
7 个 event double,文本用 17 位有效数字 round-trip;header 保存实际数量与 PSF 参数。
triangle 范围 [0,130882);按未截断的局部 magnification 再筛选:
| 区域 | 原始 tile | magnification | 最大捕获实际数 | 占用 32px 中心 tiles | 最大中心密度 |
|---|---|---|---|---|---|
| 普通区域 | RA252/Dec048(Dec −42°) | [0,1.2) | 12,765 | 8 | 4,691 |
| 银心视场密集区域 | RA262/Dec060(Dec −30°) | [0,2) | 65,536(到上限) | 30 | 7,778 |
| 强放大区域 | 同上 | [2,1e6) | 16,454 | 367 | 176 |
普通、强放大子集用完后没有复制事件凑足 65,536。事件文件名后缀表示请求上限,实际数量 以 header 和 manifest 为准。实际 bbox、flux/support 范围、中心 tile 分布及事件 hash 见 events_manifest.json。三种真实输入的 support 均为 45.84777786185942px;变化 support/wing/边缘另由合成 fixture 覆盖。
分散对照只平移完整处于画面内部的事件中心,保留 fractional phase(浮点平移舍入以内)、 flux 和 support;本来裁切的事件不移动。每次都重新计算并断言实际 event–pixel 贡献数 完全不变:真实和分散的 65,536 事件均为 432,818,979 个贡献。没有以裁切减少工作量。
原型与 ownership
每 chunk≤16,384 events。CPU 按 cache 遍历 support 的完整包围矩形建立所有相交 tile 引用,PSF wings 可以进入多个 tile;GPU 用原来的圆形行范围再筛选,继续四点 phase cache 插值和 double RGB。每个像素由一个线程累计,不使用全局 double atomic。
第一次朴素实现反复计算 phase、sqrt/行范围,4,096 普通事件的回放约 25–27 ms,慢于 atomic。第二版为每个 chunk 在 GPU 预计算 phase、颜色×flux 和行范围,然后供像素线程复用。 分散对照随后触发 128 MiB 部分和限制,进程已停止。最终版让≤256 引用的单列表 tile 直接写回独占 HDR 像素;只有长列表分段才写部分和,第二阶段按固定 task 次序相加。 这种修正保持内存上限,避免为整屏稀疏 tiles 分配一幅额外 double HDR。
设备上固定复用:references 32 MiB、tasks 2 MiB、starts 128 KiB、partials 128 MiB, 以及最多 16,384 事件的 Prepared/行范围约 12.875 MiB;合计额外预留 175 MiB。 超出引用/任务/部分和容量立即报错,无隐式切换。全部缓冲由单个实验 sink 持有,单 stream 顺序消费、同步后复用;每个 partial 元素都被覆盖写入,不需要 memset。最终样本实际 scratch 使用峰值约 37.26 MiB,整个 CPU-reference+GPU 进程 RSS 最大 717,172 KiB。 预留量和实际用量不同,RSS 包含 CPU HDR/reference/cache,不能当作生产额外 RAM。
独立最终回放结果
下表是 replay_wall 中位数(ms,三次):包含 scratch 分配、分桶、上传、预计算、累积、
合并、下载、清理,排除公共 sink/cache 初始化和 CPU reference。日志另报 complete_replay
(加公共 GPU sink 创建)、CPU_reference、cache build、完整 PROCESS_WALL,避免混淆。
| 输入 | 实际 events | atomic | tile16 | tile32 |
|---|---|---|---|---|
| 普通 | 12,765 | 26.423 | 18.511 | 19.286 |
| 银心视场 | 16,384 | 31.803 | 22.621 | 23.247 |
| 强放大 | 16,384 | 26.536 | 23.814 | 25.388 |
| 银心视场 | 65,536 | 104.107 | 69.823 | 73.093 |
| 同等贡献分散对照 | 65,536 | 85.302 | 104.389 | 79.899 |
含公共 GPU 创建的 65,536 密集回放为 137.111 / 102.323 / 105.949 ms。
强放大 tile32 回放范围 22.801–29.410 ms,atomic 25.932–27.395 ms;三次样本不足以
证明这里的稳定提升。完整数值、范围和全部重复见 summary.log
与 final_*.log,由 final_cases.py 串行生成。
分阶段日志同时记录实际贡献吞吐量。atomic 上传/kernel/download 使用 HIP event; 候选分桶为 CPU wall,prepare/accumulation/merge 为包含 launch+stream sync 的 host wall。 它们不能拿来做精确的纯 kernel 周期归因,完整回放 wall 才是算法比较依据。 分散 tile16 的分桶本身约数十 ms,足以抵消其累积优势。
编译器资源记录 显示 atomic kernel
62 VGPR,prepare 37,tile accumulation 21,merge 18,private segment 均为 0。
生成的 atomic 代码仍有三个 global_atomic_cmpswap_b64 循环;候选不需要它们。
这不是运行时 cache/occupancy/FP64 counter 测量,不能据此分摊 atomic contention 的比例。
没有使用降低 HDR 精度、近似黑体颜色或改变 min-Y/tail 的方法。
CPU producer 独立测量
诊断 consumer 在正常查询、inverse mapping、频移、黑体积分与 prepare/classification
之后,仅计数与计算摘要。输出明确标记 DIAGNOSTIC ONLY, no HDR。
parallel 模式每 worker 计数/摘要独占;汇总 checksum 与事件顺序无关,串行捕获仍保留顺序。
indexed 模式从同一有界 CSV 预构建原生一度 tile 索引,worker 查询前已完全只读,不执行 I/O。
为了比较完整相同工作而不受事件上限/调度停止次序影响,银心诊断 triangle 范围缩为
[0,40151),其他仍 [0,130882)。所有以下运行均未触顶,四种模式逐项核对
cached/wing/direct/discarded/events 和 checksum 完全一致。各三次中位数:
| 输入 | events | memory/1 worker | memory/16 | indexed/1 | indexed/16 |
|---|---|---|---|---|---|
| 普通 | 12,765 | 2.8123 s | 0.3502 s | 0.0729 s | 0.0125 s |
| 银心视场 | 16,895 | 1.1472 s | 0.1383 s | 0.0535 s | 0.00986 s |
| 强放大 | 16,454 | 1.3845 s | 0.1493 s | 0.6836 s | 0.0751 s |
CSV 全扫描明显夸大查询成本;生产判断应使用 indexed 列。强放大子集遍历大量分散 triangle,
其独立 producer 时间在这一小输入上高于 GPU 回放,说明进一步加速 GPU 未必改善同等比例的
端到端时间。这不是全天 CPU 下限,也不能与另一事件数量的回放直接相减。
未修改黑体积分;没有把 summed generation / workers 当作独立计时。
正确性与失败记录
- 全部真实回放、分散对照和最终 45 次独立复测通过 finite/double HDR 检验。
- 边界 fixture:32,771 events,33 wing-clipped, exact/intermediate phases、屏幕内外、热点、三 chunk/缓冲复用。atomic、tile16、tile32 均覆盖中途 finish/download → CPU direct → upload → 继续累积。
- 全部最终+边界最大
max_abs=5.96856e-11、max_rel=5.98529e-13;最坏 RGB 总通量 相对差≤2.83419e-14,Y≤1.15193e-14。沿用旧 replay 的 abs/rel<1e-10,另增加总 RGB/Y 相对误差≤1e-10 的检查,没有为结果放宽门槛;现有生产 primitive 的 rel≤1e-12 也通过。 - 捕获/索引诊断回归通过:真实 mixed classification cached=2/direct=1,min-Y 场 discarded=3;串行/并行/索引摘要一致;验证 event cap、非法范围、拒绝覆盖已有文件。未用提高 min-Y 代替 producer 测量。
- HIP primitive、 Minkowski mixed/min-Y integration通过。
- Schwarzschild CPU / HIP同一 8,192 星子集分类一致; 24,883,200 个 FITS float32 样本完全一致。 此处测试的是保留的生产路径;tile 原型的 double 正确性由回放验证,不冒称已接入 renderer。
make -j1 test通过(33.44 s)。
保留三类早期非零退出:沙箱未暴露 GPU、v2 分散输入的 scratch 超限、读取器误拒绝合法 wing-clipped support。后者的修复保留 event 的物理 support,仅在实际遍历时限制 cache 范围。 未删失败日志,未在任何失败后不加分析自动扩大测试规模。
最小复现
从仓库根目录先按 build_commands.txt 构建。 固定输入已随报告保留;原大 catalog/lens map hash 在 manifest。已有日志拒绝覆盖,重复 运行请使用新标签和新的事件输出路径:
python3 benchmarks/hip_psf_replay_2026-09-07/run.py repeat_capture 60 \
build/Release/capture_psf \
output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens \
benchmarks/hip_psf_replay_2026-09-07/center.csv \
0 130882 65536 /tmp/gr-psf-repeat.events 1e13 1e8 0 0 2
python3 benchmarks/hip_psf_replay_2026-09-07/run.py repeat_atomic 45 \
build/Release/replay_psf /tmp/gr-psf-repeat.events 65536 atomic
python3 benchmarks/hip_psf_replay_2026-09-07/run.py repeat_tile16 45 \
build/Release/replay_psf /tmp/gr-psf-repeat.events 65536 16
python3 benchmarks/hip_psf_replay_2026-09-07/run.py repeat_tile32 45 \
build/Release/replay_psf /tmp/gr-psf-repeat.events 65536 32
以上是重跑示例,repeat_* 标签本次未执行;实际执行命令逐条保存在各原始日志。