当波前执行时,它提供细粒度的多线程。这样做的后果之一是没有分支预测要求,如下图所示:
但我无法理解这一点。有人可以用简单的方式解释一下吗?
当波前执行时,它提供细粒度的多线程。这样做的后果之一是没有分支预测要求,如下图所示:
但我无法理解这一点。有人可以用简单的方式解释一下吗?
分支在指令流的执行中引入了显着的延迟。如果处理器不支持推测执行,则在执行分支条件之前不允许执行任何指令。如果采用分支,则处理器需要获取新的指令行,这会引入额外的延迟。如果未采用分支,则可以继续执行。在深层管道上,条件的评估可以引入 10-20 个周期。分支预测和推测执行允许处理器继续执行附加指令,或者如果采用分支,则开始提前获取指令。如果分支预测不正确,则必须丢弃分支之后的所有指令(回滚)。
分支预测硬件通常在面积方面很昂贵,但即使是基本的分支预测(可能采用与可能未采用)也可以显着改善 IPC。
GPU 不倾向于实现分支预测,至少有 3 个原因:
分支预测的目标是通过推测执行指令而不是等待条件结果和可能的额外指令获取来改进 IPC。GPU 旨在通过在多个执行线程之间免费切换来隐藏延迟。当一个扭曲/波前正在等待确定分支条件的结果时,可以发出其他扭曲/波前以隐藏延迟。
分支历史表在面积方面很昂贵。
投机执行在面积方面是昂贵的。
它在幻灯片中说,每次只有一条指令在流水线中。分支预测的目的是防止指令管道被错误的分支填满(加载 if 部分只是为了实现它应该已经将 else 指令加载到管道中)。如果只有一条指令在管道中,则不需要这样做,因为在您意识到它是错误的分支之前,您没有投资填充管道的 x 阶段(快速谷歌:最多 30 个),必须冲洗管道并重新开始。
一些细节取决于实际的 GPU 架构。但是一个简化的例子,除了 Trudbert 已经给出的答案 (+1) :
对于这样的分支
if (data[threadIndex] > 0.5) {
data[threadIndex] = 1.0;
}
可能存在该语句所针对的一组线程,以及该语句所针对的true
另一组线程false
。可以将其想象为该语句所针对的线程false
只是等待其他线程完成它们的工作。
类似地,对于这样的分支
if (data[threadIndex] > 0.5) {
data[threadIndex] = 1.0;
} else {
data[threadIndex] = 0.0;
}
可以将其想象为所有线程都执行分支的两条路径,并确保忽略“错误”路径的结果。这被称为“预测执行”。
(有关这方面的更多详细信息,请参阅GPU Gems 2,第 34 章)
因此,由于预测“正确”分支没有优势(因为无论如何每个线程都必须采用所有分支),因此没有理由引入分支预测。