13-compute-shaders

第 13 篇:计算着色器(Compute Shaders)

原文:Part 13

一句话定位

计算着色器脱离固定图形数据流,直接调度线程组;它复用 GPU 的宽执行、寄存器、缓存和内存系统,并显式暴露组内共享存储与同步。

调度层级

Dispatch
└─ 多个 Workgroup / Thread Group      ← 组之间通常无执行顺序保证
   ├─ 多个 Invocation / Thread         ← 每个有 ID 与私有寄存器
   └─ 被硬件切成一个或多个 Wave/Warp  ← 真正的执行/调度批次

“GPU thread”不是 OS 线程:通常没有独立程序计数器和栈,也不被逐线程独立调度。硬件以 wave/warp 运行同一指令,用掩码表达分支。API 定义的 workgroup 大小与硬件 wave 宽度不是同一概念;一个 workgroup 可包含多个 wave。

输入从哪里来

CS 的固有输入主要是 dispatch/workgroup/local/global ID。真实数据由 shader 根据 ID 从 buffer、image、constant/uniform 或 descriptor 指向的资源中读取。这种模式让同一程序可覆盖规则数据域,也把地址计算和边界检查责任交给程序。

组内共享存储与屏障

workgroup/shared/local memory 是同一组 invocation 可见的低延迟片上存储,适合 tile、归约、直方图和数据复用。它容量有限,并会影响同时驻留的 workgroup 数量。

屏障要拆成两个问题:

  1. 执行同步:组内参与者是否都到达某一点?
  2. 内存可见性:某类写入何时、对哪个作用域的读者可见?

只解决其中一个,程序仍可能错误。组内 barrier 通常不能同步不同 workgroup;跨组依赖一般要拆成多个 dispatch,并通过 API barrier/queue dependency 建立全局顺序,或使用目标 API 明确定义的原子与前进保证。

SIMT 效率

  • 分支分歧会让同一 wave 的路径串行化;
  • 全局内存访问若能合并为连续事务,带宽利用更好;
  • 共享存储可减少重复全局访问,但可能有 bank conflict;
  • 寄存器、共享存储和 workgroup 大小共同限制 occupancy;
  • 更多 occupancy 只是在需要隐藏延迟时有益,不是独立性能目标。

与图形流水线的关系

CS 与 VS/PS 往往共享通用执行核心,但输入/输出协议不同。图形阶段由固定功能单元自动产生顶点、quad 和插值输入;CS 直接由 dispatch 产生逻辑线程,并显式读写资源。计算结果若随后被图形管线读取,驱动必须安排 cache 可见性、布局转换和执行依赖。

术语对照

通用称呼 Vulkan/OpenGL D3D 中文理解
workgroup workgroup thread group 共享局部存储与组内 barrier 的线程集合
invocation invocation thread 逻辑执行实例
subgroup subgroup wave/warp(厂商术语) 硬件近似锁步执行子集
shared memory shared/workgroup memory groupshared 组内共享片上存储
barrier barrier GroupMemoryBarrier 等 执行和/或内存顺序原语
atomic atomic operation interlocked operation 对共享位置的不可分割更新

面向 UMD/KMD 的阅读提示

  • 编译器:追踪 local size、subgroup lowering、shared-memory layout、barrier 和 atomic 的 ISA 映射。
  • UMD:追踪 dispatch packet、descriptor、资源访问标记,以及 compute→graphics / graphics→compute barrier。
  • KMD:观察 compute queue 是否是独立硬件队列、如何与 graphics queue 建立 fence/semaphore 依赖、抢占粒度是什么。
  • 调试 hang 时优先检查:非一致 barrier、越界地址、无限自旋、跨 workgroup 假设,以及等待的信号是否可能永远不产生。

自测与实验

  • 为什么把 workgroup size 设得越大不一定越快?
  • barrier() 前后若只有部分 invocation 进入该分支,会发生什么?
  • 写 storage buffer 后立即把它作为 vertex buffer 使用,需要哪类执行与内存依赖?
  • 比较 AoS 与 SoA 访问,观察内存合并和 cache 行利用差异。

本篇总结

计算着色器把 GPU 的批量并行能力直接交给程序员,也把数据布局、同步、负载均衡和资源占用的责任一并交了出来。

posted @ 2026-10-26 22:00  Sailxiv  阅读(2)  评论(0)    收藏  举报