你让32个人排成一队,按同一个口令做事。走到岔路时,有人向左,有人向右。看似可以分头行动,但领队仍要先带一批走完,再带另一批走。NVIDIA GPU里的线程分歧,大致就是这个问题。
这项研究实测了从 Pascal、Ampere、Hopper 到 Blackwell 的多代GPU,想回答一个沿用多年的疑问:硬件更新了这么多次,遇到分支时,GPU还会不会把不同路径逐条执行?答案是,在作者测试的场景里,会。Blackwell改变了管理分支和重新合队的内部机制,却没有改变程序员实际承担的基本成本。
本文数字和结论均来自这项单一研究,尚未获得独立团队交叉验证。作者测试的是专门隔离线程分歧的微基准,不代表所有程序和工作负载。
32个线程,为什么不能各走各的?
NVIDIA GPU通常把32个线程编成一个小队,称为 warp。它们共享一条取指令的通道,步调一致时效率最高。
麻烦出现在 if/else。如果同一个 warp 里的线程根据数据选择不同分支,就发生线程分歧(warp divergence)。硬件要分别执行各条路径;执行其中一条时,不走这条路的线程只能闲着。等各条路径完成后,线程还要在共同的后续指令处重新合队,这叫重汇合(reconvergence)。
研究者关心的不只是“分路会变慢”,还包括两个更具体的问题:路径数量翻倍,时间是否也只是翻倍?重新合队会不会带来额外且迅速膨胀的开销?
为此,他们在 GTX 1080、RTX A6000、RTX 3090、H100、Jetson AGX Thor 和 RTX 5080 上运行微基准。测试覆盖数据中心和消费级 Blackwell,并用 Volta 之前的 Pascal 作基线。每个动态测量点取201次运行的中位数;研究还结合硬件性能计数器,以及对编译器生成的 SASS——NVIDIA GPU实际执行的专有机器指令——进行静态分析。
分成几路,就大致付几份成本
核心结果很直接。假设一个 warp 分成 条路径,测得耗时近似满足:
其中 是每条路径的固定成本。也就是说,从一条路径增加到32条路径,成本近似线性增加。作者在被测GPU上没有观察到超线性的重汇合惩罚:重新合队并未在逐路执行之外,再制造一笔越来越大的额外账单。
硬件计数器给出了相互吻合的证据。warp每发出一条指令,平均真正工作的线程数随路径数量按 下降。两路分歧时,每条指令平均约有16个线程工作;32路分歧时,平均只剩1个。问题的本质不是硬件停下来等待,而是它要重复发出更多指令,每次只有部分线程在干活。
这也解释了另一个容易误判的结果:提高 occupancy 没有消除惩罚。occupancy 指一个GPU计算单元里同时驻留了多少个 warp;更多 warp 通常能在一队等待时换另一队上场,从而遮住等待延迟。但线程分歧增加的是指令发出量,不只是等待时间。队伍再多,也不能替已经分路的队伍少走几趟。
Volta带来的“独立”,不是免费并行
Volta一代开始引入 Independent Thread Scheduling(ITS,独立线程调度),让同一 warp 内的线程拥有更独立的执行状态,也便于处理复杂同步。它很容易让人产生一种直觉:既然线程更独立,分歧路径或许也能更自由地并行。
实测没有支持这个推断。Ampere、Hopper和两种Blackwell在作者的测试中都呈现相同的线性成本模型。更关键的是,Volta之前的 Pascal 也遵循同样规律。换句话说,这套程序员可见的成本模型早于 ITS;ITS改变了线程如何保持进度和同步,却不意味着不同路径从此可以免费同时运行。
作者还测试了 predication(谓词化):不让线程真正跳到不同分支,而是把两边的指令都排好,再用每个线程的真假条件决定哪些结果生效。对于研究中的短小两路分支,这种做法消除了分歧路径的串行化成本,从 Pascal 到 Blackwell 都成立。
但这不是“所有分支都应改成谓词化”。谓词化可能让线程执行本来用不到的指令,而材料没有量化这笔额外工作。它更像一项需要权衡的工具,而非通用答案。
表面没变,底下已经换了几套机关
有意思之处正在这里:运行成本稳定,不等于硬件内部停滞。
Pascal使用每个 warp 一套 SSY/SYNC 指令栈,记录线程应该在哪里重新合队。后来的架构改用 barrier-register instructions,也就是用显式的屏障寄存器指令管理重汇合。
编译器选择的合队位置也在变化。所谓 immediate post-dominator,是各条分支最早必然共同到达的位置。研究的静态分析发现,晚于这个位置才合队的 deferred reconvergence(延后重汇合)案例,从 Ampere 的29个降到 Hopper 的7个,再降到 Blackwell 的2个。这里的29和2是案例数,不是百分比或性能提升;材料没有交代案例集合之外更广泛代码的统计代表性。
Blackwell还出现了 Ampere和Hopper没有的控制流结构:两级 convergence barrier、用于标记确定不会分歧的 BRA.U uniform branch,以及显式的 partial-mask WARPSYNC。两级屏障把真正的最终合队点 .RECONVERGENT,与可以让部分线程提前退出的局部合队点 .RELIABLE 区分开来。
研究者直接翻转编译后二进制中的相关位,再运行修改过的程序。在他们测试的单 warp 场景中,输出、完成状态、周期数和若干同步行为都没有变化。因此作者把新的 barrier class 解释为编译器和汇编器使用的静态分类;这只能说明当前测试未观察到运行时影响,不能证明它在所有环境里都没有作用。
为什么值得关注?
这项工作的价值,不是宣布Blackwell“没有进步”,而是把两件常被混在一起的事拆开了。
对写AI内核和性能模型的人,旧经验仍有用:在被测架构和分支结构里, 路分歧近似付出 份成本;堆高 occupancy 不能把它藏起来;适合的短分支可以考虑谓词化。不能因为用了更新的GPU,就默认线程分歧已经被硬件自动解决。
对编译器、反汇编器和性能分析工具的开发者,结论恰好相反:不能把Ampere或Hopper的控制流规则原样套到Blackwell。程序员看到的账单相似,记账系统却已经换了。
局限与未知
- 这是单一研究团队的结果。具体GPU、编译工具链和微基准虽有披露,但仍需独立复现与真实应用验证。
- 测试刻意隔离了路径串行化,没有分离真实程序中常与它同时出现的内存分歧。
.RELIABLE的位翻转实验主要限于 sm_110 上的单 warp 场景,不能排除多 warp 调度、分析器或调试器等未测试环境中的作用。