Files
GR-raytracing/benchmarks/hip_psf_replay_2026-09-07.md
T
wyj 7ddc58515a Doc: Record full-day parallel prebinning results and next steps
Document the producer-private adaptive path, the dummy support workload
diagnostics, the negative result of the old serial binning and the
2026-09-13 full-day comparison (splat 282.944 s vs atomic 481.417 s).
Add the corresponding raw logs, hotspot fixtures and runner evidence,
and lay out the staged plan toward a sub-240 s full-day render without
changing the default atomic path.
2026-09-14 19:16:00 -04:00

501 lines
35 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HIP PSF 有界真实事件回放与像素归约实验(2026-09-07)
## 结论与交付
**当前方向(2026-09-13):搁置旧串行 adaptive 的慢因追溯,在新版 worker 私有预分桶
adaptive 上优化生产管线。以下各日期记录保留历史结论;当前结果和下一步目标以
“2026-09-13 全天复测与下一步目标”一节为准。**
已实施原计划的有界捕获/回放、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](hip_psf_replay_2026-09-07/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 并发。
## 2026-09-12 持续回放与 production 集成
在提交 `2d01c2c101ccea8193a64bb46ceafca3009f0ef5` 之上的未提交实现中,回放器增加了
1--512 轮有界重复模式,用同一真实事件流测试持续负载。重复模式不把累计 128/256 轮的
GPU HDR 与单轮 CPU reference 比较,因而输出明确标记 `validation=skipped-for-sustained-timing`;
单轮真实输入与 mixed boundary 仍执行原有 double HDR、RGB/Y 通量和 finite 检查。
原 replay tile16 在密集输入的 256 轮完整 wall 为 12.968 s,atomic 为 14.326 s,只有
1.10×--1.18× 的持续收益;tile accumulation 本身仍约快 1.4×,CPU 的整屏嵌套列表分桶
约占 1.8--1.9 s。不同运行顺序下的 128 轮 adaptive 为 6.372--6.880 s,对应 atomic
7.149--7.165 s,证明短回放的 1.40× 完整收益不能直接外推。
production sink 随后接入稀疏 touched-tile 分桶和可复用有界 scratch。默认保持 atomic;
`HIP_PSF_ACCUMULATION=adaptive` 启用与 replay 相同的中心密度选择规则。32 MiB references、
2 MiB tasks 或 128 MiB partials 超限时按 chunk 回退 atomic,不改变 double RGB、四点 phase
cache、圆形 support、wing clipping 或 direct fallback 顺序。
最终同 binary(SHA-256
`c560c193e1dc2104030ed804ea68e16ab7576592191dbf147b917a6e097a66b6`)连续回放
65,536 个真实银心事件 128 轮:
| production sink | 完整 replay wall | GPU 阶段 | selector | CPU bin | upload | batches |
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
| atomic | 7.164 s | 7.132 s | 0 | 0 | 0.023 s | 512 atomic |
| adaptive | 4.631 s | 3.875 s | 0.018 s | 0.607 s | 0.091 s | 512 tile16 |
完整 replay 为 **1.55×**,记录的 GPU 阶段为 **1.84×**。同 binary 的 64 轮同贡献分散
输入中,adaptive 选择 256/256 atomic chunks,完整 wall 为 3.167 s,直接 atomic 为
3.169 s,差异在 0.1% 内。最终 dense 单轮检查的
`max_abs=2.71051e-19`、`max_rel=1.96115e-14`。最终 mixed boundary
覆盖 2 个 tile16、1 个 atomic chunk 和中途 direct fallback,最坏 `max_abs=5.96856e-11`、
`max_rel=5.95958e-13`,RGB/Y 通量阈值均通过。production primitive 在 adaptive 环境下也
通过,`max_abs=2.84217e-14`、`max_rel=7.53192e-16`。
三 tile、21,087-star renderer 配对使用同一 4K lens map 和同一 production binary
(SHA-256 `f51cbccac135502440f005c5d61d95d6004be7d4ec5cd09bfe04bab53053143d`)。
atomic/adaptive 均产生 156,837 events;adaptive 选择 14 tile16 + 2 atomic batches,kernel
为 0.118894 s,对照 0.169212 s,splat wall 为 0.236/0.285 s。两张 PNG 的 SHA-256 都是
`99a971fac7f5e66f0a1aafd0921b61f16fcb933c9488320f95e423542d3b6a6d`。约 1.4 s 的完整
进程受 cache build 等固定成本波动支配,不能用 process wall 判断这项优化。
随后使用同一 4K lens map、598,264,924 events 和 36,530 batches 运行了完整全天
adaptive 渲染。它推翻了上述有界样本的外推:
| 完整全天 | splat wall | kernel | CPU bin | selector | upload | process wall |
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
| atomic | 480.500 s | 477.302449 s | 0 | 0 | 1.411367 s | 533.62 s |
| adaptive | 586.763 s | 416.265471 s | 155.302 s | 2.212 s | 7.506981 s | 640.35 s |
adaptive 的 GPU kernel 只减少 61.037 s(12.79%),而串行关键路径上的 CPU 分桶增加
155.302 s,splat wall 因而增加 106.263 s(22.12%),完整进程增加 106.73 s(20.00%)。
36,515/36,530 batches 被选为 tile16,说明中心 32px tile 密度无法预测完整 47px PSF
support 扩张后的 references、tasks、列表长度和分桶成本。atomic 从有界回放的
13.93 ms/batch 到全天的 13.07 ms/batch 没有恶化;tile kernel 则从有界样本的
7.57 ms/batch 变为全天的 11.40 ms/batch,CPU 分桶另需 4.25 ms/batch。串行分桶是已确认的额外成本;GPU 阶段变慢的具体原因未定位,
不能仅凭这些时间排除时钟或其他系统因素。
正确性仍成立:atomic/adaptive PNG 的 SHA-256 都是
`c63df730c7f927fc6b6ae17df5ffbad1d2bb44631a5821557150d00d6269a3e4`。两个 HDR FITS
共有 24,883,200 个 float,113 个因累积顺序不同;`max_abs=2.38418579e-07`、
`max_rel=1.18905923e-07`。这项旧串行分桶 adaptive 实现是历史负结果,不能外推为新版并行预分桶的结论;
默认继续保持 atomic。当时提出的下一轮实验是直接度量 support-expanded 引用工作量,并在
重新跑完整全天前用真实流式 producer 验证并行预分桶或 GPU 分桶能否把成本移出串行关键路径。
完整 adaptive 原始输出保存在 `full_production_adaptive_user.log`(SHA-256
`ec7b41d56a76cb93383737c30c6c6055bdb53b9b0cff54034333d96a841b1f36`);该用户命令未嵌入
Git/binary hash,运行后工作区 binary 的 SHA-256 为
`f51cbccac135502440f005c5d61d95d6004be7d4ec5cd09bfe04bab53053143d`,不可仅凭事后 hash
证明执行期间 binary。atomic 数字来自同一任务先前保留的终端输出。
### 2026-09-12 producer 私有并行预分桶原型
在上述完整全天负结果之后,将 adaptive 选择与 support-expanded CPU 分桶移到每个 OpenMP
producer 私有的 `HipPsfPreparedChunk`,在获取 sink 共享锁前完成;单个 sink 仍独占 GPU
HDR、stream、device scratch 和稳定的上传 staging。direct fallback 先准备本 worker 的待提交
chunk,再在同一锁内完成提交、HDR 下载、CPU splat、HDR 上传。原 `hip_psf_sink_submit` 仍用于
单线程回放兼容,正常生产默认 atomic 未变。新日志记录 tile references、tasks、merges 和
单 chunk 峰值,以便下一次评估完整 support 工作量。
同一 65,536-event 银心固定输入重复 128 轮,均为 512 个 tile16 batches。新 binary 的配对
回放结果如下(两者均通过 `128 × CPU double reference`,`max_rel=2.14616e-14`):
| 生产 sink 回放 | replay wall | 累计 CPU bin | GPU 阶段 | process wall |
| --- | ---: | ---: | ---: | ---: |
| sink 内串行分桶 | 3.886 s | 0.549 s | 3.659 s | 5.778 s |
| 16 worker 私有预分桶 | 3.958 s | 0.709 s(各 worker 求和) | 3.670 s | 5.873 s |
此输入上并行预分桶没有端到端收益,且累计 CPU 工作与 RSS 上升(约 716→770 MiB)。由于这
份输入已被全天结果证明低估真实分桶与 tile kernel 成本,此试验仍不能判断全天会否受益,
更不能宣称 61 s 的 kernel 收益已被回收。**不据此再跑完整全天。**需要先取得代表实际
36,530 chunks 的 support-expanded references/tasks 分布和并行分桶 wall,再决定是否继续此方向。
真实小型 4K lens-map renderer 中,16 workers 处理 156,837 events,13 tile +3 atomic
batches;13 个 tile chunk 共 6,145,194 references、64,056 tasks、5,465 merges,单 chunk
最多 561,449 references。PNG SHA-256 与先前 atomic 输出同为
`99a971fac7f5e66f0a1aafd0921b61f16fcb933c9488320f95e423542d3b6a6d`。另一个
32,771-event mixed boundary 回放包含 2 tile +1 atomic chunk 和 direct fallback,通过 CPU
double reference,`max_abs=5.96856e-11`、`max_rel=5.95958e-13`。HIP primitive 与
`make -j4 ENABLE_PNG=1 test` 均通过。
新原始日志:`parallel_prebin_{serial_128_validated,16workers_128_validated}.log`、
`parallel_prebin_renderer_workload.log`、`parallel_prebin_mixed_boundary.log`、
`parallel_prebin_hip_primitive.log`。先前 `parallel_prebin_16workers_128.log` 因 OpenMP
`reduction(max:failed)` 的私有初值而没有提交事件;原始失败保留,修正为 `reduction(+:failed)`
后的 `*_v2.log` 才是首次有效回放,最终数字以上述带 scaled reference 校验的日志为准。
为获取不经 GPU 的真实全天 support 分布,dummy 后端增加显式
`DUMMY_PSF_SUPPORT_STATS=1` 诊断:每 worker 保存最多 16,384 个事件,在 chunk flush 时按
production 的 cache-limited 矩形 support 统计 16px references、touched tiles、按 256
references 切分的 tasks、最大单 tile 列表和第一遍计数耗时。它不生成 HDR、不 materialize
references、不上传 GPU,不能把第一遍耗时等同于完整两遍分桶成本。21,087-star 小样通过,
原始记录为 `parallel_prebin_dummy_support_small.log`;该样的 chunk 边界受 OpenMP 动态调度
影响,不与 HIP renderer 的逐 chunk 列表配对。完整全天诊断结果见下文。
下一次完整全天诊断使用与已跑的 dummy 任务相同的参数,只额外设置环境变量;输出路径仅
满足 CLI,dummy 不写图像:
```sh
OMP_NUM_THREADS=16 OMP_DYNAMIC=FALSE DUMMY_PSF_SUPPORT_STATS=1 \
./build/Release/schwarzschild_sky_dummy --verbose \
--psf-relative-tail 1e-8 --psf-min-y 0 --max-cache-psf-flux 1e8 \
--all-sky-catalog assets/2mass/processed/all_sky --exposure 1e13 \
--psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 --catalog-load-workers 4 \
--lens-map-input output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens \
--output /tmp/2mass_dummy_support_diagnostic.png
```
用户随后运行了上述完整全天 dummy 诊断;原始终端输出为
[`full_dummy_support_user.log`](hip_psf_replay_2026-09-07/full_dummy_support_user.log),
SHA-256 `992a3109de28a338c53af229b6a3b4083659a835f78929c36d36178358a6d5e0`。
日志未嵌入执行时 Git/binary hash;运行后本地 dummy binary 的 SHA-256 为
`2550fbdc7367ec4d56bdf87894e1322d7f4af5165e93a17af3e6a37806c0649a`。
同一 343,363,141 stars 产生 598,264,924 cached events,0 direct/wing/discard;
64,440 catalog tiles 全部加载,49.020 s;16 worker 分类/chunk wall 81.760 s。zsh `time`
给出总时间 2:11.91;zsh 对 pipeline 中的 `tee` 另列一行,不能把两个 2:11.91 相加。
该次动态调度产生 36,508 个满 chunk、16 个 partial;与 HIP 的 36,530 batches 不作逐批
配对,但总事件数一致。
| 全天满 chunk support 统计 | p50 | p90 | p99 | max |
| --- | ---: | ---: | ---: | ---: |
| 16px references | 746,748.5 | 802,816 | 802,816 | 802,816 |
| touched 16px tiles | 49 | 168 | 1,036 | 1,521 |
| tile tasks | 2,975 | 3,136 | 3,435.93 | 3,733 |
| 最大 tile 列表 | 16,384 | 16,384 | 16,384 | 16,384 |
| 第一遍计数 | 0.807 ms | 0.919 ms | 1.049 ms | 7.969 ms |
全部 chunk 合计 27,216,790,943 references、107,847,441 tasks,worker 第一遍计数时间之和
29.347 s。这是并行 worker 时间之和,**不是**额外 wall time,也不包括第二遍写 references、
任务构造、锁内 staging 或 GPU 上传。全天 HIP 串行完整分桶为 155.302 s,不能拿 29.347 s
直接替换它。第一遍显示每个事件平均覆盖约 45.5 个 16px tile;满 chunk 的 p90 已到
`16,384 × 49`,且最大列表从中位数起就是整批事件。
对旧真实 `center_65536.events` 逐 chunk 用相同 support 矩形计算,四批 references 为
745,430 / 725,200 / 753,474 / 749,671,接近全天 p50;但 touched tiles 为
96 / 162 / 203 / 222,最大列表仅 14,637 / 9,099 / 11,188 / 9,220。因此先前有界
样本只匹配了引用总量,没匹配热点集中度。为区分这两个量,`make_hotspot_fixture.py` 把
原事件平移到相同整数像素,或保留约 8×8px 位置散布;颜色、flux、support 原样保留,
亚像素余数仅受 double 舍入影响。这两份**明确是反事实 GPU workload,不是物理星像**。
固定热点每批恰好 802,816 references、49 tiles、3,136 tasks、最大列表 16,384;
输入 SHA-256 分别为 `de39e07d420f70aaa2f7309d209e58a1091d2bea4ca6d8332366e6944f19347b`
与 `87f90c2e43845962702e1643f9b7a635108b75b6e21a30080650442745cadcf6`。
| 128 轮、512 批回放 | atomic wall | tile 串行 wall | tile 并行 wall | atomic GPU 阶段 | tile GPU 阶段 |
| --- | ---: | ---: | ---: | ---: | ---: |
| 同一整数像素 | 7.711 s | 4.001 s | 4.071 s | 7.677 s | 3.760 s |
| 8×8px 散布 | 6.482 s | 3.949 s | 4.046 s | 6.447 s | 3.714 s |
全部回放通过按轮数缩放的 CPU double reference,tile 的最大相对误差不超过
`3.30e-14`。此对照说明 refs/tile/list 聚合量不足以重现全天 tile GPU 阶段
`416.265/36,530 = 11.40 ms/batch`:即使强制匹配 p90 热点,回放仍约
`7.3 ms/batch`。另外在 `center_65536.events` 的同一回放进程内放入 15 个 CPU 忙等线程,
atomic/tile GPU 阶段为 7.126/3.669 s(512 批),几乎仍是无忙等线程的
7.13/3.66 s;简单主机抢占也未重现全天差距。上述 workload 与争用实验均为诊断性
反事实,不能改变真实全天 adaptive 慢 20% 的结论。
原始配对日志:`hotspot_{atomic,adaptive_serial,adaptive_parallel}_128.log`、
`hotspot_jitter8_{atomic,adaptive_serial,adaptive_parallel}_128.log`、
`busy_center_{atomic,adaptive}_128.log`。全天 adaptive 原始进度每隔约 5 秒报告累计 HIP
阶段:首尾约 7–8 ms/batch,中间约 12–13 ms/batch 持续数万批。这提示当前固定 65,536
events 输入未覆盖真实流中的长期困难区段,但也不能排除其他随时间变化的系统因素;
原因仍未定位。当时提出从该区段捕获真实 events 和逐批 GPU/CPU 明细;
2026-09-13 已搁置这项旧版追溯,不再作为新版推进的前置条件。
其余原始证据为 `final_production_{atomic,adaptive}_128.log`、
`final_production_adaptive_dense.log`、
`final_production_dispersed_{atomic,adaptive}_64.log`、
`final_production_adaptive_mixed.log`、`final_hip_test_adaptive.log` 和
`final_renderer_{atomic,adaptive}.log`。每份日志包含完整命令、timeout、Git hash、binary hash
及原始输出。production 默认值没有改变。
实现入口:
- [capture_psf.c](../tests/capture_psf.c):调用真实 producer 的测试专用 consumer,捕获或诊断,不生成 HDR。
- [replay_psf.hip](../tests/replay_psf.hip):CPU double reference、现有 atomic、两种 tile 原型。
- [make_psf_fixture.c](../tests/make_psf_fixture.c):单独标记的合成边界/热点/wing fixture。
- [test_psf_capture.py](../tests/test_psf_capture.py):边界限制、分类、串行/并行/索引摘要、拒绝覆盖验证。
- [全部原始证据与索引](hip_psf_replay_2026-09-07/README.md)。
## 2026-09-13 全天复测与下一步目标
用户在重新构建 worker 私有预分桶版本后,再次完成同配置全天 adaptive 渲染;随后
`git stash` 回到 `2d01c2c`,重新构建并复测原 atomic,之后用 `git stash pop` 恢复修改。
该 HEAD 的 HIP 实现不读取 `HIP_PSF_ACCUMULATION`,所以 atomic 复测命令虽仍写着
`adaptive`,实际是 atomic;不能把输出文件名或环境变量当作算法证据。
| 全天实现 | splat wall | GPU event 阶段 | CPU bin | upload | process wall |
| --- | ---: | ---: | ---: | ---: | ---: |
| 历史 atomic | 480.500 s | 477.302449 s | 0 | 1.411367 s | 533.62 s |
| 旧串行 adaptive | 586.763 s | 416.265471 s | 155.302 s,串行 | 7.506981 s | 640.35 s |
| 新并行预分桶 adaptive | 282.944 s | 256.184375 s | 134.374 s,worker 累加 | 7.184765 s | 335.75 s |
| 本次 atomic 复测 | 481.417 s | 478.336515 s | 0 | 1.432135 s | 534.37 s |
四次总事件数均为 598,264,924、batches 均为 36,530;两次 adaptive 都选择 36,515 tile16
和 15 atomic batches。新 adaptive 无 direct/wing/discard,references 为 27,216,530,468、
tasks 为 107,238,420、merges 为 2,802,462,峰值 references/chunk 为 802,816。
新 adaptive 和旧 adaptive 均已使用相同 payload 的黑体 LUT;catalog 加载分别为
49.334/50.104 s。新版 bin 时间是各 worker 的经过时间之和,可以与 GPU 重叠,不能加到
splat wall 上,也不能与旧版串行 bin 作等口径的关键路径比较。
atomic 的 splat/GPU 复测仅比历史值高约 0.2%。相对本次 atomic,新 adaptive 的 splat
快约 1.70×、GPU event 阶段快约 1.87×、完整进程快约 1.59×。这支持继续推进新版;
尚不是相同 binary 内的 atomic/adaptive 配对,也不证明新版全天 HDR 数值正确性。
新旧 adaptive 的 splat 差 303.819 s,其中 GPU event 阶段差 160.081 s;不能把全部收益
归因于分桶并行化。旧版 GPU 阶段为何更慢仍未知,保留历史证据,**停止专项追溯**;仅当
新版出现可重复退化或正确性问题且旧版信息有助定位时重新调查。
新 adaptive 完整原文见
[full_parallel_prebin_adaptive_user_2026-09-13.log](hip_psf_replay_2026-09-07/full_parallel_prebin_adaptive_user_2026-09-13.log);
atomic 复测仅收到结尾摘录,原样保存为
[full_atomic_redo_user_2026-09-13_excerpt.log](hip_psf_replay_2026-09-07/full_atomic_redo_user_2026-09-13_excerpt.log)。
两者均未提供运行时 binary hash,摘录不能代替完整命令和完整运行日志;本次只更新文档,
没有重新运行 benchmark 或比较新生成的全天 HDR。
### 新版优化目标与验证顺序(待实施)
目标是在相同 RX 9070、4K lens map、全天 catalog、PSF/曝光/黑体参数和 HDR/PNG 输出下,
将完整进程从 335.75 s 推进到 **240 s/张以内**。这是待验证目标,不是性能承诺;不能通过
降低精度、删减事件、改变 tail/min-Y、缩小输入或省略输出来达标。atomic 保留为参考和
显式可选路径,本次不修改默认算法。
用户全程观察新版的 btop:GPU 常在约 94%,会反复降至约 80%,并非偶发;整机 CPU
持续满载。用户另报告原 atomic 能吃满 GPU。旧串行 adaptive 当时没有观测,不能推断它
不存在 GPU 不满载现象。上述是人工观测,未保存同步遥测,不能据此量化净算力利用率。
新版 generation/submission 累计分别为 814.275/3712.364 s,后者包含分桶、锁等待和
提交/完成等待;atomic 复测的 GPU 阶段占 splat wall 约 99.36%,进程仍为 1461% CPU。
CPU 满载不等于有效 producer 工作,忙等是需测量的嫌疑,尚未定量确认。
新版非 splat 阶段约 52.806 s;即使消除 splat wall 与 GPU event 阶段之间的全部
26.760 s,总进程仍约 309 s。若其他阶段不变,240 s 目标要求 splat 不超过约 187.2 s,
比当前 GPU event 阶段还低约 27%。该 event 区间包围 prepare/accumulate/merge,可能含
提交间隙,不等同于三个 kernel 的净执行时间。因此同时调查管线空隙和 GPU 执行成本,
不能把 btop 达到 100% 当作验收标准。
1. 先比较已有新版 adaptive 与 atomic 全天 HDR:finite、逐像素误差、RGB/Y 总通量,
使用现有正确性阈值;记录输出 hash,不为这一步重跑全天。
2. 增加可关闭的有界诊断,拆分 CPU 分桶、锁等待、锁持有、GPU 完成等待、staging 和
提交时间,记录线程 CPU time;GPU 分别测 prepare、accumulate、merge,并保留原总区间。
在新版代表性真实流式小样上同步记录 GPU busy、时钟、功耗、温度,先验证测量开销。
固定事件回放用于隔离成本,不能单独替代生产 producer/sink 的端到端证据。
3. 若批间空隙显著,优先评估双缓冲 staging/上传,使下一批准备与当前批 GPU 执行重叠;
若共享锁争用显著,再对照专用提交线程加有界队列。这些是待验证候选,不是已选定实现。
明确缓冲 ownership、完成后复用和有界背压;单 sink 持有 GPU HDR,保留 direct fallback
的 finish/download/CPU/upload 顺序,不引入 per-event task 或无界排队。
4. 管线改善后重测剩余成本;若主要时间仍在 kernel,则优化占比最大的实际 kernel;若
catalog 加载成为主要限制,再单独评估输入阶段。保留密集、分散和 mixed/direct 回归。
有界配对采用相同 binary/输入、预热后至少三次交错顺序复测,报告 wall、CPU time、
GPU 分阶段及波动,不累加重叠 worker 时间。每次预设 timeout,串行独占执行,保留完整
命令、Git/diff/binary/input hash、原始日志与退出码;GPU 不可用直接失败。
5. 有界正确性与收益验证后再另行安排全天配对确认,同时报告完整进程和分阶段时间。
未达到 240 s 时记录剩余差距及实测瓶颈;不为解释旧版而额外运行全天。
## 环境与测量纪律
Git 基线 `5eccc31c99db96de2a0597babf2fd4c2149e91e7`,测量时在此基础上有未提交修改。
没有覆盖用户已有的计划修改。生产 `src/hip_psf.hip` 未改;`src/frame.c` 的诊断钩子
仅在 standalone 测试编译时启用。每次直接执行的 binary SHA256 在相应日志中;
[源码、binary、lens map hash](hip_psf_replay_2026-09-07/source_binary_manifest.json)、
[宿主环境](hip_psf_replay_2026-09-07/metadata.log)、
[构建命令](hip_psf_replay_2026-09-07/build_commands.txt)与 `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](hip_psf_replay_2026-09-07/input_manifest.json)
和 [重建脚本](hip_psf_replay_2026-09-07/prepare_inputs.py)。没有遍历完整全天 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](hip_psf_replay_2026-09-07/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](hip_psf_replay_2026-09-07/summary.log)
与 `final_*.log`,由 [final_cases.py](hip_psf_replay_2026-09-07/final_cases.py) 串行生成。
分阶段日志同时记录实际贡献吞吐量。atomic 上传/kernel/download 使用 HIP event;
候选分桶为 CPU wall,prepare/accumulation/merge 为包含 launch+stream sync 的 host wall。
它们不能拿来做精确的纯 kernel 周期归因,完整回放 wall 才是算法比较依据。
分散 tile16 的分桶本身约数十 ms,足以抵消其累积优势。
[编译器资源记录](hip_psf_replay_2026-09-07/device_resources.log) 显示 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](hip_psf_replay_2026-09-07/fixture_generate.log):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 也通过。
- [捕获/索引诊断回归](hip_psf_replay_2026-09-07/capture_indexed_regression.log)通过:真实 mixed
classification cached=2/direct=1,min-Y 场 discarded=3;串行/并行/索引摘要一致;验证
event cap、非法范围、拒绝覆盖已有文件。未用提高 min-Y 代替 producer 测量。
- [HIP primitive](hip_psf_replay_2026-09-07/hip_primitive.log)、
[Minkowski mixed/min-Y integration](hip_psf_replay_2026-09-07/minkowski_integration.log)通过。
- [Schwarzschild CPU](hip_psf_replay_2026-09-07/schwarzschild_cpu.log) /
[HIP](hip_psf_replay_2026-09-07/schwarzschild_hip.log)同一 8,192 星子集分类一致;
[24,883,200 个 FITS float32 样本完全一致](hip_psf_replay_2026-09-07/schwarzschild_hdr.log)。
此处测试的是保留的生产路径;tile 原型的 double 正确性由回放验证,不冒称已接入 renderer。
- [`make -j1 test`](hip_psf_replay_2026-09-07/cpu_regression.log)通过(33.44 s)。
保留三类早期非零退出:沙箱未暴露 GPU、v2 分散输入的 scratch 超限、读取器误拒绝合法
wing-clipped support。后者的修复保留 event 的物理 support,仅在实际遍历时限制 cache 范围。
未删失败日志,未在任何失败后不加分析自动扩大测试规模。
## 最小复现
从仓库根目录先按 [build_commands.txt](hip_psf_replay_2026-09-07/build_commands.txt) 构建。
固定输入已随报告保留;原大 catalog/lens map hash 在 manifest。已有日志拒绝覆盖,重复
运行请使用新标签和新的事件输出路径:
```sh
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_*` 标签本次未执行;实际执行命令逐条保存在各原始日志。