我对GPU如何执行同步有一些疑问。 据我所知,当一个warp遇到障碍时(假设它在OpenCL中),并且它知道同一组的其他warp还没有到达那里。所以它必须等待。但是在等待时间里,这种扭曲到底是做什么的呢? 它仍然是一个活跃的扭曲?或者它会做某种空操作?
正如我所注意到的,当我们在内核中进行同步时,指令数量会增加。我想知道这个增量的来源是什么。同步是否分解为许多较小的GPU指令?或者因为空闲的warp会执行一些额外的指令?
最后,我强烈想知道同步增加的成本与没有同步的成本相比(假设屏障(CLK_LOCAL_MEM_FENCE))是否受工作组(或线程块)中的warp数影响? 感谢
答案 0 :(得分:7)
活动warp是驻留在SM上的warp,即已经分配了所有资源(寄存器等),并且warp可用于执行,只要它是可调度的。如果warp在同一个threadblock / work-group中的其他warp之前到达屏障,它仍然是活动的(它仍然驻留在SM上并且它的所有寄存器仍然有效),但它不会执行任何指令,因为它是还没准备好安排。
插入屏障不仅会停止执行,还会成为编译器的障碍:不允许编译器跨屏障执行大多数优化,因为这可能会使屏障的目的无效。这是您看到更多指令的最可能原因 - 没有障碍,编译器可以执行更多优化。
屏障的成本在很大程度上取决于您的代码正在做什么,但是每个屏障都会引入一个泡泡,所有warp必须(有效地)在它们全部再次开始工作之前变为空闲,所以如果你有一个非常大的线程块/工作组然后当然可能存在比小块更大的泡沫。泡沫的影响取决于你的代码 - 如果你的代码是非常符合内存的,那么屏障就会暴露出它们可能被隐藏之前的内存延迟,但如果更加平衡则可能会产生不太明显的效果。
这意味着在一个内存非常紧密的内核中,最好不要启动大量较小的块,这样当一个块在屏障上冒泡时,其他块就可以执行了。您需要确保您的占用率因此而增加,如果您使用块共享内存在线程之间共享数据,则需要进行权衡。