Preserve the protected full-catalog dummy run, its initial harness failure, input and output hashes, distribution quantiles, and the resulting sparse-tile scheduling conclusions.
316 lines
20 KiB
Markdown
316 lines
20 KiB
Markdown
# GPU PSF 累积计划
|
||
|
||
## 2026-09-07 更新
|
||
|
||
有界实测后,production HIP 已改为 32-thread/event 协作 kernel,并恢复 OpenMP
|
||
catalog/inverse-map/颜色计算。每个 worker 拥有一个 16,384-event 私有块,共享的
|
||
GPU sink 只在批量提交和完整 CPU direct-fallback 边界加锁,保留单份 cache/HDR。
|
||
两个 pinned host/device slot 通过 kernel completion event 控制复用;所有 batch
|
||
均计时,长任务会周期报告已提交与已回收的完成事件数。详细结果、限制、重现命令及
|
||
原始输出见 [有界排查记录](benchmarks/hip_psf_2026-09-07.md)。
|
||
|
||
三种受控事件分布支持协作 kernel 的收益;真实三 tile 子集也改善了端到端耗时。
|
||
没有据此把全部 kernel 时间归因为 atomic contention,未引入 tile-local reduction、
|
||
float HDR 或黑体近似。下面第 7 节的 2026-09-05 状态是历史基线,单线程 producer
|
||
和前 64 批计时限制已被此次实现取代。实际 `PsfCachedEvent` 为 56 B,16,384 项为
|
||
896 KiB;早期按 24–32 B 估算的整帧内存不是当前结构的实际成本。
|
||
|
||
## 后续实施结果(2026-09-07)
|
||
|
||
已实施有界真实事件捕获、CPU/当前 HIP/16×16/32×32 回放、按像素归约原型与
|
||
独立 producer 诊断;原型包含 phase/行边界复用,以及稀疏 tile 直接写回、密集列表
|
||
部分和合并。固定输入、manifest、完整原始日志与结论见
|
||
[HIP 回放实验](benchmarks/hip_psf_replay_2026-09-07.md)。
|
||
|
||
production HIP 尚未替换为 tile 算法;收益与事件分布有关,不能由局部回放推算
|
||
全天加速比。未运行完整全天 catalog。测试工具与原型已于 2026-09-11 提交为
|
||
`7f5ec1a`;以下保留原执行计划作为验收依据。
|
||
|
||
同日后续实验在 replay 中增加了按 chunk 的中心 tile 密度选择器。当前 RX 9070 配对数据中,
|
||
65,536-event 银心输入的 adaptive/atomic/tile16 中位数为 67.834/95.018/67.354 ms,
|
||
同贡献分散输入为 80.092/78.203/99.693 ms;选择扫描中位成本不超过 0.455 ms。
|
||
mixed fixture 已覆盖同一 stream 内 atomic、tile 与 direct fallback 的组合。结果支持下一步
|
||
做 production 流式集成原型,但选择器和 tile sink 目前仍只在测试程序中,未改变生产默认。
|
||
|
||
随后用只计数的 `PSF_BACKEND=dummy` 跑过用户给定的 45 度 Schwarzschild 银心全天命令,
|
||
没有启动 HIP,也没有写 HDR/PNG。598,264,924 个 cache event 中有 36,508 个满
|
||
16,384-event chunk;满 chunk 的 event-producing triangle 数 p50/p75/p90/p99 为
|
||
2/3/10/31,occupied 32px center tile 数为 1/2/5/30,全部满足当前 adaptive tile16
|
||
阈值。这把“dense replay”提升成了真实 production producer 顺序的证据,支持把 adaptive
|
||
tile16 接入 production sink 作为下一步候选。限制是 16-worker dynamic schedule 会有运行间
|
||
波动,而且 p99 chunk 含相距约 3.7K px 的稀疏簇;实现必须保留稀疏 tile 列表和 atomic
|
||
fallback,不能假定单一连续小矩形。详见
|
||
[dummy chunk 全量记录](benchmarks/dummy_psf_chunks_2026-09-11/README.md)。
|
||
|
||
## 下一步执行计划(2026-09-07,原计划;有界实验已实施)
|
||
|
||
### 依据与目标
|
||
|
||
当前实现基线为 `e1ec480669b0d24a0266ee135edf8a64a0d80ec9`。用户完成的
|
||
[全天 CPU/HIP 记录](benchmarks/2mass_galactic_center_cpu_hip_2026-09-07.md)
|
||
中,HIP 总耗时 533.06 s,splat 阶段 481.2 s,其中 kernel 476.906037 s、
|
||
event upload 1.504570 s。下一步优先降低 GPU PSF 累积成本,暂不优先优化
|
||
geodesic、增加 CPU workers 或改造传输流水线。
|
||
|
||
用户随后提供的同一 lens map 导入 CPU 运行总耗时 1402.02 s,splat 阶段
|
||
1350.3 s;与 HIP 对应的时间比分别为约 2.63 和 2.81。这组后续数据来自本次
|
||
会话,尚未在上述 benchmark 中归档完整原始日志。单星重新生成几何的 67.35 s
|
||
包含固定开销,也支持几何不是当前主要成本;它不是独立的纯 tracing 计时。
|
||
|
||
kernel 占比高不能单独证明 atomic contention 主导。以下分桶原型用于检验这个
|
||
假设,不预先承诺加速倍数,也不直接替换 production 路径。
|
||
|
||
### 1. 建立有界真实事件回放
|
||
|
||
- 从小型 catalog 子集和已有 lens map 的选定 triangles 捕获正常准备后的
|
||
`PsfCachedEvent`,覆盖普通区域、银心密集区域和强透镜区域。保留位置、颜色、
|
||
flux、support、事件顺序及相匹配的 PSF cache 参数;不收集完整六亿事件。
|
||
- 捕获器必须限制输入子集、triangle 范围和输出事件数,不能只限制输出文件大小、
|
||
却仍遍历整个全天 catalog。记录输入与事件文件 hash、选择规则和实际覆盖分布。
|
||
- 首轮按 4,096、16,384、65,536 events 递增;单次回放上限 45 s,小型 renderer
|
||
上限 60 s。超时后先分析,不自动扩大规模。空间分散的合成对照单独标记,保持
|
||
事件数、flux 和 support 分布可比,避免把屏幕裁切减少的工作量当作收益。
|
||
- 对同一回放比较 CPU double reference、当前 32-thread/event kernel 与候选算法。
|
||
除 events/s 外,统计实际 event–pixel 贡献数和贡献吞吐量;拆分上传、分桶、
|
||
累积、合并、下载时间,并测量整个回放 wall time 与内存峰值。
|
||
|
||
交付物:有界捕获/回放工具、固定输入与 manifest、完整命令及原始日志。
|
||
先获得可重复的当前基线,再进入候选算法对照。
|
||
|
||
### 2. 原型验证按像素归约
|
||
|
||
- 分别试验 16×16 和 32×32 screen tiles。根据事件完整 support 构建每个 tile
|
||
的事件列表;一个事件可引用到多个 tile,不能只按中心归属,否则会丢失 PSF wings。
|
||
- 让线程拥有输出像素,在寄存器中用 double 累积 RGB,再写回 HDR。继续使用现有
|
||
四点 phase cache 插值、圆形 support 和裁切判定。目标是消除每个贡献的全局
|
||
double atomic,而不是改用低精度或减少物理贡献。
|
||
- 密集 tile 的长列表可拆成独立的部分和,再用第二阶段归约,避免一个热点 tile
|
||
限制并行度。明确部分和的 ownership、写回顺序和 scratch 生命周期。
|
||
- 保持有界 chunk;限制 tile 引用列表及部分和内存,检查索引溢出并明确超限处理。
|
||
不依赖整帧事件常驻内存。分桶、空像素遍历、合并和 buffer 清理都计入成本。
|
||
- 原型与现有 kernel 并存。若减少 atomics 后仍无收益,结合回放和设备分析检查
|
||
cache 权重读取、FP64 算术、寄存器压力与负载分布;不把失败解释为必须降低精度。
|
||
|
||
进入生产集成的条件:正确性通过,且包含分桶/合并的完整回放在代表性样本上有
|
||
可重复收益。只有 kernel 单项变快而整体变慢时,不替换当前实现。第 4、7 节原有的
|
||
tile-local 门槛在此区分为“允许有界实验检验假设”和“有收益证据才保留生产实现”。
|
||
|
||
### 3. 测量 CPU producer 独立吞吐
|
||
|
||
提供诊断 sink:保留正常 catalog 查询、inverse mapping、频移、黑体颜色、
|
||
cache/direct/min-Y 判定和事件准备,仅将累积消费替换为计数与校验摘要。
|
||
明确标记诊断输出,不能把未累积的 HDR 当作正常渲染结果。
|
||
|
||
先在同一有界输入运行该模式,测量 producer wall time,必要时细分查询、映射与颜色
|
||
计算。不要用提高 min-Y 的方式替代它:那会提前改变执行路径。现有 summed worker
|
||
generation 的 `3302.459 / 16 ≈ 206 s` 仅是粗略线索,受等待和调度影响,不能作为
|
||
独立 CPU 下限。GPU 加速后若 producer 成为限制,再据测量选择优化对象;黑体近似
|
||
或查表不在本轮默认范围内。
|
||
|
||
### 4. 正确性、集成与测试纪律
|
||
|
||
- 保持 double HDR、亚像素 phase、support、wing clip、min-Y 与 direct fallback
|
||
语义;包含跨 tile、屏幕边缘、不同 phase、大 support、热点、多 chunk、buffer
|
||
复用和混合 direct fallback 的用例。fallback 前须完成待处理 GPU 工作,保持
|
||
下载、CPU 累积、上传的完整顺序。
|
||
- 验证 finite 值、事件及分类计数、double linear HDR 的绝对/相对误差和总 RGB/Y
|
||
通量差;近零值不单用相对误差。沿用现有测试门槛作为起点,若需调整必须解释
|
||
数值原因并记录误差证据,不为通过测试任意放宽。
|
||
- 归约顺序会变化,不能承诺 PNG 比特级一致。PNG 比较是补充,不能代替 double
|
||
HDR 检验。先通过 PSF 单元回放,再做小型 Minkowski、Schwarzschild 集成回归。
|
||
- 所有测试进程严格串行;启动前确认没有前一测试仍在运行,超时后确认退出再继续。
|
||
不同时运行 CPU/HIP 对照,也不让 profiler 与另一测试竞争设备。
|
||
- 本计划不授权重跑完整全天渲染。先完成有界验证和性能证据,再决定是否需要完整
|
||
验证;没有完整运行就不宣称整帧加速比。保存 Git/binary hash、构建命令、设备与
|
||
runtime、线程、输入/cache、所有阶段计时和原始终端输出。
|
||
- 实施后同步设计文档第 22.3 节及 benchmark。原计划写入时尚未实现或执行测试;当前进展见上方实施结果,
|
||
后续提交仍须由用户明确授权。
|
||
|
||
## 1. 目的与边界
|
||
|
||
本文件规划的是**最终点源 PSF 到 HDR framebuffer 的累积**加速,而不是 GPU
|
||
geodesic tracing,也不是改变 catalog、lens map 或物理模型。
|
||
|
||
当前单帧数据流保持为:
|
||
|
||
```text
|
||
image-plane mesh -> backward ray tracing -> final lens map
|
||
-> catalog query / inverse mapping -> (x, y, linear RGB, PSF parameters)
|
||
-> PSF splat -> HDR framebuffer
|
||
```
|
||
|
||
GPU 后端只替换最后的 `PSF splat -> HDR framebuffer`。CPU 仍负责 catalog 读取、
|
||
source-triangle 查询、inverse mapping、magnification、frequency shift、黑体颜色和
|
||
`--psf-min-y` 判定。它们已经在 PSF 累积之前完成;被 `--psf-min-y` 丢弃的事件不得
|
||
上传到 GPU。
|
||
|
||
这使得光追和 PSF 是按阶段顺序执行的任务。数值时空的 time slabs 在完成 lens map 后
|
||
已经可以释放,不能把它们同 GPU PSF framebuffer、cache 或事件块当成同时占用的显存。
|
||
|
||
CPU 实现始终是正确性基线和所有机器的 fallback。GPU 是可选的 `optics/psf` 后端,不得
|
||
改变亚像素位置、Moffat 参数、`--psf-relative-tail`、`--psf-min-y`、亮星 cache/direct
|
||
fallback 语义或 HDR 输出定义。
|
||
|
||
## 2. 目标机器
|
||
|
||
| 机器 | CPU / GPU | 计划角色 |
|
||
| --- | --- | --- |
|
||
| 工作站 | i7-12700K 的 8P/16T 配置;RX 9070 系列、16 GB | GPU 原型与高吞吐生产渲染机 |
|
||
| ITX | i5-10500 ES、6C/12T;Intel 核显 | CPU-only 基线;核显只在实际基准证明有益后启用 |
|
||
| Optiplex | i7-7700、4C/8T;Radeon Pro WX 4100、4 GB | 低端离散 GPU 兼容性和加速收益测试机 |
|
||
|
||
## 3. 后端接口与事件流
|
||
|
||
默认路径不构建“全帧所有星像”的事件数组,而是流式提交有限大小的事件块。数亿事件即使
|
||
每项仅 24--32 B,也会使 host-device 流量达到十余 GiB;在内存较小的机器上,整帧数组也会
|
||
造成不必要的主存峰值。
|
||
|
||
ATRI 工作站有 128 GB RAM,因此可以提供一个明确的、可选的整帧收集模式。以约 4.92 亿
|
||
事件为例,24 B/event 约为 11.0 GiB,32 B/event 约为 14.7 GiB;即使加上索引、分桶工作区、
|
||
CPU HDR 与 catalog,仍有可用空间。其可能收益不是减少需要传给 GPU 的总事件数,而是:
|
||
|
||
- 先按屏幕 tile 或 Morton order 重排事件,使 GPU 输入有更好的空间局部性;
|
||
- 一次得到准确的各 tile 负载,用于安排多个 kernel launch / workgroup;
|
||
- 为 tile-local reduction 预先构造连续的 event ranges,避免 GPU 端动态分桶;
|
||
- 将 PCIe 传输与多个 GPU 批次的执行安排得更稳定。
|
||
|
||
这是一条 ATRI 专用的空间换时间路线,必须以端到端实测证明收益后才保留。它不应成为 ITX、
|
||
Optiplex 或通用 CPU fallback 的前提;在这些机器上仍使用流式块。
|
||
|
||
当前 CPU 已在 `optics` 层建立 cache-eligible 的事件边界:
|
||
|
||
```c
|
||
typedef struct {
|
||
double x, y;
|
||
LinearRgb color;
|
||
double flux, support_radius;
|
||
} PsfCachedEvent;
|
||
```
|
||
|
||
`psf_prepare_cached_event()` 保留既有的 cache/direct/min-Y 判定,状态 0 或 2 产出该
|
||
事件;direct fallback 在 CPU 立即处理,min-Y 在上传前丢弃。`PsfEventSink` 由每个 OpenMP
|
||
worker 初始化一次、贯穿其线程生命周期,固定容量为 16,384 个事件;填满或线程结束时由现有
|
||
CPU cache evaluator 消费。此实现是 GPU producer 的正确性基线,并已通过固定 HDR reference
|
||
和完整 2MASS 前后性能记录验证。
|
||
|
||
GPU sink 将消费同一 `PsfCachedEvent` 与现有不可变 `PsfKernelCache::weights`,不得重新以
|
||
float 解析采样替代 cache 语义。首版使用有限大小的上传块并复用 device buffer;块大小从
|
||
1--16 MiB 试起,由实测决定。GPU 后端仍必须统计:cache splat、wing clip、direct fallback
|
||
和 min-Y discarded;这些计数在块完成后汇总,而不是在热循环中同步。
|
||
|
||
为降低局部热点,CPU 侧应把来自不同 image-plane triangle / worker 的事件块交错提交。
|
||
三角形内部的星像中心必定落在各自不重叠的像平面三角形内;不同三角形的 PSF wings 仍可
|
||
重叠,故这只是改善 GPU work distribution 的低成本手段,不是互斥性假设。
|
||
|
||
## 4. GPU 累积的两级方案
|
||
|
||
### A. direct global atomic 原型
|
||
|
||
一个 GPU thread 或 thread group 处理一个 PSF event,遍历其圆形支持域,并对 HDR pixel
|
||
做浮点 atomic add。这是最小的实现,适合先测:PCIe 上传、cache 读取、PSF 算术和热点
|
||
atomic contention 各自占比。
|
||
|
||
`atomic add` 的含义是“读、加、写”不可被另一线程插入;它保证多个 thread 同时向同一
|
||
pixel 加光通量时不丢更新。它不减少物理贡献次数,也不保证浮点加法顺序,因此 GPU 输出
|
||
应以容差同 CPU reference 比较,而非要求 bitwise 相等。
|
||
|
||
### B. tile-local reduction
|
||
|
||
若 direct atomic 在银河中心等密集区域成为瓶颈,则按屏幕 tile(例如 16x16 或 32x32
|
||
pixels)分桶事件。一个 GPU block 是一组共同被调度的 threads;block 内可使用 shared
|
||
memory,即该 block 专用、片上、速度快的小型临时数组。threads 先把本 tile 的许多 PSF
|
||
贡献累积在 shared memory,最后每个 HDR pixel 只写回全局 framebuffer 一次或少数几次。
|
||
|
||
这没有少算任何光,而是把大量对同一全局 HDR pixel 的竞争写入,转换为 block 内的局部
|
||
累积。代价是分桶、边界 PSF、跨 tile wings 和负载不均衡的实现复杂度。只有 direct 原型
|
||
证明 atomic 是主要瓶颈时才进入这一步。
|
||
|
||
## 5. API 选择
|
||
|
||
### HIP / ROCm
|
||
|
||
- 适合工作站 RX 9070 的最快原型;宿主端和 kernel 都接近 C/C++ 工作流。
|
||
- 用它验证算法与性能,尤其是 direct atomic 和 tile reduction。
|
||
- Gentoo 能否稳定运行由本机实际 driver/runtime、功能探测、正确性测试和长跑决定;不得用
|
||
厂商“受支持发行版”名单作为可用与否的判断标准。
|
||
- WX 4100 / Polaris 不应被假定能运行当前 ROCm 栈。因此 HIP 是高性能候选,不是三机共同
|
||
的部署承诺。
|
||
|
||
### Vulkan compute
|
||
|
||
- 是跨 Intel 核显、WX 4100 和 RX 9070 最有价值的正式可选后端;使用现有图形驱动的 Vulkan
|
||
compute path,宿主端保持 C。
|
||
- shader 编译为 SPIR-V;启动时枚举设备、显存、workgroup 限制和所需 feature。
|
||
- 浮点 `atomicAdd` 不是 Vulkan core。direct-atomic 路径必须检查
|
||
`VK_EXT_shader_atomic_float` 的对应 feature;没有则不能悄悄降级为错误结果。
|
||
- 不支持 float atomic 的设备可走 tile-local reduction,或明确回退 CPU。后者是首版可接受
|
||
行为。
|
||
|
||
### OpenCL
|
||
|
||
- 可作为单机实验或能力探测选项,但不作为主线接口。
|
||
- 各 Gentoo 主机上具体 OpenCL ICD、Mesa/Rusticl 或 AMD runtime 的设备暴露和 feature 组合
|
||
需实际检查,不能从 API 名称推断。
|
||
- 若未来 Vulkan 覆盖不足,再基于真实测得的设备矩阵决定是否值得维护 OpenCL 后端。
|
||
|
||
## 6. 精度与验收
|
||
|
||
GPU 后端必须先在小、固定 catalog snapshot 上同 CPU 的 `--psf-direct` 或 cache reference
|
||
对比。比较 linear HDR RGB/Y,而不是仅比较 tone-mapped PNG。
|
||
|
||
验收项:
|
||
|
||
1. 相同输入、固定输出尺寸、固定 PSF 参数与固定 catalog tile set。
|
||
2. 记录每通道绝对/相对误差、最大像素误差、总 RGB/Y 通量差和事件统计。
|
||
3. 单星(不同 phase、亮/暗、边缘和大 support)、稀疏场、密集重叠场各有测试。
|
||
4. 验证 `--psf-relative-tail`、`--psf-min-y`、cache/direct fallback 的统计及图像语义一致。
|
||
5. 当用户显式选择 GPU 后端时,GPU 不可用、feature 不足、初始化失败或运行错误必须明确报错
|
||
并终止该次渲染;不得回退 CPU 或默默输出部分帧。未选择 GPU 时,CPU 路径仍是独立基线。
|
||
6. 以端到端 wall time 为准,同时记录 CPU 线程数、GPU、driver/runtime、块大小、分辨率、
|
||
catalog snapshot、Git hash 和参数。
|
||
|
||
浮点原子加法的规约顺序随调度变化,GPU 与 CPU double HDR 不会 bitwise 相同。这是可量化的
|
||
数值差异;容差要由上述固定输入对照决定,而不是预先假设。
|
||
|
||
## 7. 实施顺序
|
||
|
||
### 当前状态(2026-09-05)
|
||
|
||
已完成 CPU event 路径:`PsfCachedEvent`、`psf_prepare_cached_event()` 与 per-worker
|
||
`PsfEventSink` 已进入 `frame_splat_catalog()`。固定 HDR reference 与 unit tests 验证该路径
|
||
不改变输出;在 2MASS 全天 1080p 的前后比较中,完整 event 实现相对无 event 路径版本增加
|
||
0.99% user CPU work。该记录含完整命令和原始输出,见
|
||
`benchmarks/2mass_all_sky_psf_event_sink_2026-09-05.md`。
|
||
|
||
曾有一个 float、解析中心采样的 HIP atomic spike,用于确认 HIP runtime、上传与 float atomic
|
||
可执行;它没有 cache 权重、双精度 HDR 或 production integration。其 `test-hip` target 和测试
|
||
已移除,不能作为 renderer GPU backend 的验证或运行入口。
|
||
|
||
HIP direct-atomic 的当前实现状态:
|
||
|
||
1. 已定义 production HIP sink 的 C ABI,上传 double event 与 immutable cache 权重,并复用
|
||
device/HDR buffer。正式构建选项为 `PSF_BACKEND=cpu|hip`;HIP 选择会把该层链接到 renderer,
|
||
而 CPU 选择不要求 HIP 工具链或 runtime。
|
||
在 RX 9070(gfx1201)上,`make -B PSF_BACKEND=hip SPACETIME=minkowski hip-psf-test`
|
||
的三事件重叠 cache 对照给出 `max_abs=3.4694469519536142e-18`、
|
||
`max_rel=2.7555746842446215e-16`。
|
||
2. 已接入 `frame` 的流式 sink。`PSF_BACKEND=hip` 使用单一 GPU double HDR framebuffer;
|
||
cache 事件按 16,384 项块提交,仍使用既有 bilinear phase cache、圆形支持和 wing clip 规则。
|
||
direct fallback 会完成前序 GPU 工作、在 CPU 计算、再上传 HDR 后继续,因而保持提交顺序。
|
||
3. RX 9070 上的 640×360 固定 Minkowski catalog HDR 对照逐样本一致;含 2 个 cache 事件与
|
||
1 个 direct fallback 的 `tests/data/hip_psf_mixed_catalog.csv` 场同样逐样本一致。GPU failure
|
||
会打印阶段与 HIP 错误并令该帧返回失败,不会切换到 CPU backend。
|
||
4. 已在 RX 9070 上记录一个受控的高密度 endpoint:54,160 星的 1920×1920、0.6 deg
|
||
2MASS tile 产生 26,172 个 cache event、零 direct fallback。HIP 的 2 个 batch 中 H2D
|
||
为 0.073 ms、kernel 为 2.950 s、D2H 为 11.256 ms;CPU/HIP PNG 字节一致。完整命令、
|
||
原始输出、Git 基线、线程、设备、分辨率和 PSF 参数见
|
||
`benchmarks/hip_psf_direct_atomic_dense_tile_2026-09-05.md`。
|
||
5. 该 endpoint 说明当前时间主要位于 device kernel,而非 PCIe;它**不能单独证明** kernel
|
||
时间主要来自热点 atomic contention(仍混有每 event 的 PSF 遍历与 cache 读取)。因此暂不
|
||
实现 tile-local reduction。下一步应在资源隔离条件下,以不同屏幕密度和 PSF 支持域分离竞争
|
||
效应;只有该证据显示竞争为主导且 tile-local 的整帧端到端测量获益时,才保留分桶/重排实现。
|
||
ATRI 的整帧收集/重排同样必须以端到端收益证明。
|
||
6. HIP 路径稳定后再评估 Vulkan 的可移植后端及其他机器的实际设备矩阵。
|
||
|
||
每一步独立提交,并保持 CPU reference、GPU runtime 层和 shader 资源的提交边界清晰。
|