我对GPU如何执行同步有一些疑问。
据我所知,当一个warp遇到一个障碍时(假设它在OpenCL中),并且它知道同一组的其他warp尚未出现。因此,它必须等待。但是,这种扭曲在等待时间内到底能做什么?
它仍然是活跃的经线吗?还是会执行某种空操作?
如我所注意到的,当我们在内核中进行同步时,指令的数量会增加。我想知道这个增量的来源是什么。同步是否分解为那么多较小的GPU指令?还是因为空闲的经线执行了一些额外的指令?
最后,我强烈想知道,与没有同步的情况相比,同步所增加的成本(比如说barrier(CLK_LOCAL_MEM_FENCE))是否会受到工作组(或线程块)中扭曲的数量的影响?
谢谢
最佳答案
Activity 的warp是驻留在SM上的warp,即所有资源(寄存器等)均已分配,并且warp是可调度的,因此可以执行该warp。如果warp在同一线程块/工作组中的其他warp之前到达屏障,它将仍然处于 Activity 状态(它仍驻留在SM上,并且其所有寄存器仍然有效),但是由于它不执行任何指令还没准备好排定。
插入屏障不仅会阻碍执行,而且会成为编译器的屏障:不允许编译器对屏障进行大多数优化,因为这可能会使屏障的目的无效。这是您看到更多指令的最可能原因-在没有障碍的情况下,编译器能够执行更多优化。
屏障的成本非常依赖于代码的工作,但是每个屏障都会产生一个气泡,在此气泡中,所有线程束都必须(有效)变为空闲,然后它们才能再次开始工作,因此,如果您有一个很大的线程块/工作组,那么当然有一个更大的泡沫,而不是一个很小的泡沫。气泡的影响取决于您的代码-如果您的代码受内存的限制很大,则屏障将在可能被隐藏的位置暴露内存延迟,但是如果平衡得更好,则效果可能不太明显。
这意味着在内存非常有限的内核中,最好启动大量较小的块,以便当一个块在屏障上冒泡时,其他块也可以执行。因此,您需要确保占用率增加,并且如果要使用块共享内存在线程之间共享数据,则需要权衡取舍。
关于cuda - GPU中的同步,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6676384/