Preserve user-provided complete CPU and HIP logs and associate the optimized implementation with e1ec480669. Record matching event counts, user-confirmed bit-identical PNG output, and the 2.77x workflow speedup with tracing/import differences noted.
Mark the pre-artifact-fix CPU benchmark as historical and link the new paired result.
205 lines
12 KiB
Markdown
205 lines
12 KiB
Markdown
# HIP PSF 有界排查与优化(2026-09-07)
|
||
|
||
后续用户完成了全天空 CPU/HIP 配对运行,并确认 PNG 比特级一致;见
|
||
[完整 4K 记录](2mass_galactic_center_cpu_hip_2026-09-07.md),其中记录了本次优化提交的实际 hash。
|
||
本页保留提交前有界排查的原始上下文。
|
||
|
||
## 范围与结论
|
||
|
||
本次没有运行用户的完整 343,363,141 星 / 598,308,919 星像任务。
|
||
所有 renderer/benchmark 都单进程顺序执行,前一个退出后才启动下一个;单次微基准
|
||
45 秒超时,缩小 renderer 60 秒超时。没有并发性能测试,没有删除原 render 输出。
|
||
|
||
源码基线为 `265d7b95d5b916ec4768d174d73ad963a43f0088`,优化版是此基线上的未提交改动。
|
||
最初保留了用户现存 HIP binary;另从该 Git commit 的干净源码重建旧版,以复核对照。
|
||
主机 HIP 7.2.53210-9999,AMD Radeon RX 9070 / gfx1201;性能测试设置
|
||
`OMP_NUM_THREADS=16`,catalog loaders 为 4。Release / `-O2`;HIP 显式
|
||
`--offload-arch=gfx1201`。完整元数据见 [metadata.log](hip_psf_2026-09-07/metadata.log)。
|
||
|
||
已确认的实现问题与处理:
|
||
|
||
- 旧 HIP 分支将 catalog 查询、逆映射、频移与黑体积分串行化。现在按 triangle 使用
|
||
OpenMP producer,每 worker 一个 16,384-event 私有块,GPU cache/HDR 只分配一次。
|
||
- 旧 kernel 一线程串行遍历一个 PSF,double atomic 编译为 64-bit CAS 重试循环。
|
||
现在每个 event 用 32 线程访问相邻像素;保持四点 phase cache、圆形 support 和
|
||
double RGB 累积。分布实验支持这一改变,不把全部 kernel 时间归因为 atomic 竞争。
|
||
- 旧 host 缓冲是可立即复用的普通 malloc 数组;现在 sink 同步复制进自己拥有的两个
|
||
pinned slot,重用 host/device slot 前等待上一 kernel 完成,生命周期不依赖 pageable
|
||
`hipMemcpyAsync` 的运行时暂存行为。GPU copy/kernel 仍在同一 stream 内顺序执行。
|
||
- 旧计时只覆盖前 64 批。现在两个 slot 的计时 event 循环使用,统计全部批次,并约每
|
||
5 秒在提交时打印进度。完成数是已回收计时的完成数,最多有两个未回收 slot。
|
||
- chunk 提交与整个 CPU direct-fallback 的 download/evaluate/upload 持有同一共享锁。
|
||
没有 per-star 锁,没有共享可变 CPU scratch,没有改变 backend 错误时立即失败的行为。
|
||
|
||
未使用分桶规约、float HDR、近似黑体积分或改变 min-Y/tail 参数。
|
||
|
||
## 受控 kernel 实验
|
||
|
||
使用 `tests/benchmark_hip_psf.hip` 生成固定 LCG seed 12345 的相同事件。frame 3840×2160,
|
||
FWHM 2.7,beta 4.5,tail 1e-8,cache radius 47;每个事件 56 B。
|
||
每个进程先计算串行 CPU double HDR reference,再执行一个 HIP replay。CPU reference
|
||
耗时不是 production 16-thread CPU render 的性能基线。
|
||
|
||
| 事件数 | 中心分布范围 | 旧 kernel | 32-thread kernel 原型 | 比值 |
|
||
| ---: | ---: | ---: | ---: | ---: |
|
||
| 4,096 | 16 px | 22.490 ms | 5.702 ms | 3.94× |
|
||
| 16,384 | 1 px | 137.888 ms | 23.976 ms | 5.75× |
|
||
| 16,384 | 3840 px(y 限于2160) | 55.630 ms | 21.492 ms | 2.59× |
|
||
|
||
原型阶段仅改变 kernel 的线程分工,保留旧上传和计时实现,便于隔离效果。
|
||
原始输出:[旧密集](hip_psf_2026-09-07/baseline_dense.log)、
|
||
[新密集](hip_psf_2026-09-07/wave_dense.log)、
|
||
[旧热点](hip_psf_2026-09-07/baseline_hotspot.log)、
|
||
[新热点](hip_psf_2026-09-07/wave_hotspot.log)、
|
||
[旧分散](hip_psf_2026-09-07/baseline_spread.log)、
|
||
[新分散](hip_psf_2026-09-07/wave_spread.log)。
|
||
|
||
整合双缓冲后的 65,536-event/16px replay:4/4 批均计时,kernel 78.268 ms,replay wall
|
||
83.762 ms;CPU reference 842.402 ms。double HDR max_abs `1.7053025658242404e-13`,
|
||
max_rel `3.3472443502765663e-15`,总 RGB flux 相对差 `-1.3316774058238102e-17`。
|
||
[原始输出](hip_psf_2026-09-07/final_multibatch.log)。
|
||
|
||
## 原 4K lens map 的真实 catalog 子集
|
||
|
||
保留原文件 `output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens`:
|
||
3840×2160、45°、65,817 vertices、130,882 triangles。未重新 tracing/refine。
|
||
|
||
使用 tile 索引的主对照输入只有三个 tile:RA252/Dec048、RA262/Dec060、RA082/Dec090。
|
||
每个 tile 均匀抽取最多 8192 行,共 21,087 颗星,产生 156,837 个星像。
|
||
准备脚本和源/子集 SHA256:[prepare_inputs.py](hip_psf_2026-09-07/prepare_inputs.py)、
|
||
[input_manifest.log](hip_psf_2026-09-07/input_manifest.log)。
|
||
其余 tile 故意缺失,因此 prefetch 的 64,437 unavailable 是缩小输入条件,不是生产数据错误。
|
||
|
||
| 实现 | catalog/splat(日志四舍五入) | GPU kernel 合计 | 完整进程 |
|
||
| --- | ---: | ---: | ---: |
|
||
| 原有 HIP binary | 1.9 s | 1.469529 s | 2.971 s |
|
||
| 干净旧源码重建 HIP | 1.9 s | 1.496493 s | 3.016 s |
|
||
| 优化 HIP | 0.4 s | 0.168641 s | 1.487 s |
|
||
| CPU 16 workers | 0.6 s | — | 1.674 s |
|
||
|
||
所有实现均 cached=156837、wing-clipped=0、direct=0、discarded=0。
|
||
优化版 GPU 16 批全部计时;producer wall=0.326 s,worker generation 总和=2.053 s,
|
||
submission/fallback 总和=1.157 s。worker wall 总和包含并发时间,不能加到 GPU 时间上。
|
||
|
||
原始日志:[旧 HIP](hip_psf_2026-09-07/baseline_multi.log)、
|
||
[优化 HIP](hip_psf_2026-09-07/final_multi.log)、[CPU](hip_psf_2026-09-07/cpu_multi.log)。
|
||
干净源码旧版复核另见 [clean_baseline_multi.log](hip_psf_2026-09-07/clean_baseline_multi.log)。
|
||
|
||
旧 HIP 与优化 HIP 的 kernel 时间相差约 8.7 倍、完整进程约 2 倍;这些是小规模单次测量,
|
||
不是完整全天空的加速比。相较 CPU,本子集的完整进程收益较小,cache 初始化和 4K 输出
|
||
占比较高。没有依此预测用户完整任务的完成时间。
|
||
|
||
辅助诊断保留了同一 lens map 的单 CSV 模式:256 星及 8192 星。
|
||
8192 星时旧/新 splat 为 4.4/0.6 秒,完整进程 5.489/1.706 秒。
|
||
但单 CSV 会放大逐 triangle 扫描成本,不能用它代表生产 tile 索引的 CPU 占比。
|
||
同 8192 星改用 tile 索引后,旧 kernel=0.171626 秒,新 kernel=0.028882 秒。
|
||
日志:[256](hip_psf_2026-09-07/baseline_lens256.log)、
|
||
[CSV旧](hip_psf_2026-09-07/baseline_lens8192.log)、
|
||
[CSV新](hip_psf_2026-09-07/final_lens8192.log)、
|
||
[索引旧](hip_psf_2026-09-07/baseline_indexed.log)、
|
||
[索引新](hip_psf_2026-09-07/final_indexed.log)。
|
||
|
||
## 验证
|
||
|
||
- `make -j1 test`:通过;固定 HDR、camera、geodesic、frame、Schwarzschild、observer track、
|
||
catalog prefetch、CLI 和多线程 movie/lens map 回归均通过。
|
||
[完整日志](hip_psf_2026-09-07/cpu_regression.log)。
|
||
- `test_hip_psf`:213 事件、71 次 submit,全部计时;覆盖 host 数组立即覆写、slot 复用、
|
||
画面边缘、wing clipping 和中途 CPU HDR 修改后继续 GPU。
|
||
[初次日志](hip_psf_2026-09-07/streaming_test.log)、
|
||
[最终重建后日志](hip_psf_2026-09-07/streaming_test_final.log)。
|
||
- `tests/test_hip_renderer.py`:96×64、4 workers,先 CPU 后 HIP;验证 cached=2/direct=1
|
||
的混合场和 discarded=3 的 min-Y 场。统计一致、FITS float32 HDR payload 完全一致。
|
||
[完整日志](hip_psf_2026-09-07/renderer_regression.log)。
|
||
- 4K 子集的旧/新 HIP 以及 CPU/新 HIP:24,883,200 个 FITS float32 样本完全一致;PNG
|
||
也一致。double 精度由上述 sink/replay tests 单独验证,未将 FITS 当作 double 文件。
|
||
[比较日志](hip_psf_2026-09-07/hdr_comparison.log)。
|
||
- 在单个子进程设置 `ROCR_VISIBLE_DEVICES=''`,32×24 的显式 HIP render 报设备不可用、
|
||
非零退出且没有写图。[原始输出](hip_psf_2026-09-07/fail_fast.log)。
|
||
- 初次 mixed fixture 使用 exposure=2 未越过 support 阈值,测试断言正确拒绝了无 fallback
|
||
的输入;依据源码改为 exposure=1000 后才通过。这是测试输入校正,非 production 修复。
|
||
[初次输出](hip_psf_2026-09-07/fixture_calibration_failed.log)。
|
||
|
||
## 可复制命令
|
||
|
||
以下使用 zsh 默认 `time`,不设置 GNU 风格 `TIMEFMT`。命令必须顺序执行;任何失败或
|
||
超时后先确认前一个进程已退出。原始输出保存在上述链接,未只保留汇总值。
|
||
|
||
```zsh
|
||
# 从本仓库根目录执行;准备固定样本,输出源与子集哈希。
|
||
python3 benchmarks/hip_psf_2026-09-07/prepare_inputs.py
|
||
|
||
# 独立重建旧源码,不改变当前 checkout。
|
||
mkdir -p /tmp/gr-hip-baseline-src
|
||
git archive 265d7b95d5b916ec4768d174d73ad963a43f0088 Makefile src mk | tar -x -C /tmp/gr-hip-baseline-src
|
||
make -j4 -C /tmp/gr-hip-baseline-src PSF_BACKEND=hip SPACETIME=schwarzschild ENABLE_HDR=1 \
|
||
HIP_CXXFLAGS='--offload-arch=gfx1201 -std=c++17 -O2 -Wall -Wextra -Wpedantic' backend
|
||
|
||
# 当前实现与 CPU reference。
|
||
make -j4 PSF_BACKEND=hip SPACETIME=schwarzschild ENABLE_HDR=1 \
|
||
HIP_CXXFLAGS='--offload-arch=gfx1201 -std=c++17 -O2 -Wall -Wextra -Wpedantic' backend hip-psf-test hip-psf-bench
|
||
make -j4 PSF_BACKEND=cpu SPACETIME=schwarzschild ENABLE_HDR=1 backend
|
||
|
||
render_args=(
|
||
--all-sky-catalog /tmp/gr-hip-catalog-multi --catalog-load-workers 4
|
||
--psf-relative-tail 1e-8 --psf-min-y 0 --max-cache-psf-flux 1e8
|
||
--exposure 1e13 --psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 --hdr-output
|
||
--lens-map-input output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens
|
||
--verbose
|
||
)
|
||
time OMP_NUM_THREADS=16 timeout --kill-after=5s 60s /tmp/gr-hip-baseline-src/build/Release/schwarzschild_sky_hip \
|
||
"${render_args[@]}" --output /tmp/gr-hip-clean-baseline-multi.png
|
||
time OMP_NUM_THREADS=16 timeout --kill-after=5s 60s ./build/Release/schwarzschild_sky_hip \
|
||
"${render_args[@]}" --output /tmp/gr-hip-final-multi.png
|
||
time OMP_NUM_THREADS=16 timeout --kill-after=5s 60s ./build/Release/schwarzschild_sky \
|
||
"${render_args[@]}" --output /tmp/gr-cpu-multi.png
|
||
|
||
# 原有 binary 的初始记录使用 /tmp/gr-schwarzschild-hip-baseline,其他参数完全相同。
|
||
# 单 tile 索引测试仅将 root 换为 /tmp/gr-hip-catalog-subset。
|
||
# 单 CSV 诊断改用 --catalog benchmarks/hip_psf_2026-09-07/catalog_8192.csv
|
||
# (或 catalog_256.csv),不用 --all-sky-catalog,输出到单独的 /tmp PNG。
|
||
|
||
OMP_NUM_THREADS=16 timeout --kill-after=5s 45s ./build/Release/benchmark_hip_psf 65536 16
|
||
OMP_NUM_THREADS=16 timeout --kill-after=5s 45s ./build/Release/test_hip_psf
|
||
make -j1 test
|
||
|
||
# 小尺寸 renderer 回归;先分别构建带 HDR 的 Minkowski CPU/HIP。
|
||
make PSF_BACKEND=cpu SPACETIME=minkowski ENABLE_HDR=1 backend
|
||
make PSF_BACKEND=hip SPACETIME=minkowski ENABLE_HDR=1 \
|
||
HIP_CXXFLAGS='--offload-arch=gfx1201 -std=c++17 -O2 -Wall -Wextra -Wpedantic' backend
|
||
python3 tests/test_hip_renderer.py build/Release/minkowski_sky build/Release/minkowski_sky_hip
|
||
python3 scripts/fits_floatdiff.py /tmp/gr-cpu-multi_HDR.fits /tmp/gr-hip-final-multi_HDR.fits
|
||
```
|
||
|
||
旧/新原型微基准可使用同一 `tests/benchmark_hip_psf.hip` 与基线 sink 源码编译:
|
||
|
||
```zsh
|
||
cp /tmp/gr-hip-baseline-src/src/hip_psf.hip /tmp/gr-hip-psf-baseline.hip
|
||
hipcc --offload-arch=gfx1201 -std=c++17 -O2 -fopenmp -Isrc -x hip \
|
||
tests/benchmark_hip_psf.hip /tmp/gr-hip-psf-baseline.hip -x none \
|
||
build/Release/obj/schwarzschild/hdr_sink1_hip/src/optics.o \
|
||
-lm -lpng -lcfitsio -o /tmp/hip_psf_bench_baseline
|
||
python3 - <<'PY'
|
||
from pathlib import Path
|
||
s = Path('/tmp/gr-hip-psf-baseline.hip').read_text()
|
||
s = s.replace('const size_t index = (size_t)blockIdx.x * blockDim.x + threadIdx.x;',
|
||
'const size_t thread = (size_t)blockIdx.x * blockDim.x + threadIdx.x;\n'
|
||
' const size_t index = thread / 32;\n const int lane = thread % 32;')
|
||
s = s.replace('int offset_x = first; offset_x <= last; ++offset_x',
|
||
'int offset_x = first + lane; offset_x <= last; offset_x += 32')
|
||
s = s.replace('(event_count + threads - 1) / threads',
|
||
'(event_count * 32 + threads - 1) / threads')
|
||
Path('/tmp/gr-hip-psf-wave.hip').write_text(s)
|
||
PY
|
||
hipcc --offload-arch=gfx1201 -std=c++17 -O2 -fopenmp -Isrc -x hip \
|
||
tests/benchmark_hip_psf.hip /tmp/gr-hip-psf-wave.hip -x none \
|
||
build/Release/obj/schwarzschild/hdr_sink1_hip/src/optics.o \
|
||
-lm -lpng -lcfitsio -o /tmp/hip_psf_bench_wave
|
||
OMP_NUM_THREADS=16 timeout --kill-after=5s 45s /tmp/hip_psf_bench_baseline 4096 16
|
||
OMP_NUM_THREADS=16 timeout --kill-after=5s 45s /tmp/hip_psf_bench_wave 4096 16
|
||
OMP_NUM_THREADS=16 timeout --kill-after=5s 45s /tmp/hip_psf_bench_baseline 16384 1
|
||
OMP_NUM_THREADS=16 timeout --kill-after=5s 45s /tmp/hip_psf_bench_wave 16384 1
|
||
OMP_NUM_THREADS=16 timeout --kill-after=5s 45s /tmp/hip_psf_bench_baseline 16384 3840
|
||
OMP_NUM_THREADS=16 timeout --kill-after=5s 45s /tmp/hip_psf_bench_wave 16384 3840
|
||
```
|