5.11. 什么是线程束执行状态?

运行 内核线程束 状态可通过多个非互斥的形容词来描述:活跃的(active)、停滞的(stalled)、就绪的(eligible)和已选择的(selected)。

线程束的执行状态通过颜色标识。图表灵感来源于 GTC 2025 的 CUDA Techniques to Maximize Compute and Instruction Throughput 演讲。

线程束 从其 线程 开始执行到所有 线程 都从 内核 退出为止,该 线程束 均被认为是 活跃的 (active)。活跃的 线程束 构成了一个资源池,线程束调度器 每个周期从中选择候选者来发射指令(即放入某个发射槽中)。

每个 流式多处理器 (SM) 上活跃的 线程束 最大数量因 架构 而异,具体可参考 NVIDIA 文档 中的 计算能力 章节。例如,在具有 计算能力 9.0 的 H100 SXM GPU 上,每个 SM 最多可容纳 64 个活跃的 线程束(2048 个线程)。需要注意的是,活跃的 线程束 不一定正在执行指令。在上图中,除了一个槽位+周期外,其余所有槽位+周期都有活跃的 线程束 —— 这表明了高 占用率

就绪的 (eligible) 线程束 是指准备好发射下一条指令的活跃的 线程束。要使一个 线程束 变成就绪状态,必须满足以下所有条件:

  • 已获取下一条指令,

  • 所需的执行单元可用,

  • 所有指令依赖关系已解析,并且

  • 无同步屏障阻碍执行。

就绪的 线程束线程束调度器 可以立即进行指令发射的候选对象。在上图中,除了 n + 2 周期之外的所有周期均存在就绪的 线程束。若多个周期内没有就绪的 线程束 可能会对性能造成负面影响,特别是当您主要使用像 CUDA 核心 这样的低延迟算术单元时。

停滞的 (stalled) 线程束 是指因未解决的依赖关系或资源冲突而无法发射其下一条指令的活跃的 线程束线程束 停滞的原因多种多样,包括:

  • 执行依赖,必须等待先前算术指令的结果,

  • 内存依赖,必须等待先前内存操作的结果,

  • 流水线冲突,执行资源当前被占用。

当线程束因访问共享内存或因执行长时间运行的算术指令而停滞时,我们称其停滞在”短计分板(short scoreboard)”上。当因访问 GPU 内存而停滞时,则称为停滞在”长记分板(long scoreboard)”上。这些是 线程束调度器 内部的硬件单元。计分板 是一种在动态指令调度中用于跟踪依赖关系的技术,其历史可以追溯到”第一台超级计算机”——Control Data Corporation 6600,其中一台在 1966 年 推翻了欧拉幂和猜想。与 CPU 不同,计分板不用于 线程 内部的乱序执行(指令级并行),而只用于跨线程的执行(线程级并行);参见 此 NVIDIA 专利

在上图中,每个周期的多个槽位中都出现了停滞的 线程束。停滞的 线程束 本身并不一定是坏事——大量并发停滞的 线程束 可能是 隐藏延迟 所必需的,这些延迟来自长时间运行的指令,如内存加载或像 HMMA 这样的 张量核心 指令,这些指令 可能运行数十个周期

已选择的 (selected) 线程束 是指在当前周期已被 线程束调度器 选中接收指令的就绪 线程束 。每个周期,线程束调度器 都会查看其就绪 线程束 资源池,如果存在任何符合条件的线程束,则选择一个并向其发射一条指令。每个存在就绪 线程束 的周期中,都有一个已选择的 线程束。在 活跃周期 中,某个 线程束 被选中并发射指令的比例就是 发射效率