Cuda线程调度 - 延迟隐藏

时间:2016-02-25 13:26:44

标签: cuda

什么是cuda线程(或整个warp),执行从全局内存读取,由调度程序进入睡眠状态?假设我在内核读取后立即在内核中进行了一些计算,这些计算不依赖于读取数据。可以在全局读取的数据还没有的时候执行吗?

1 个答案:

答案 0 :(得分:1)

读取的内存本身不会导致停顿(除非LD / ST单元不可用)。

当另一个操作需要使用该存储器读操作的结果时,将发生线程停止。

编译器知道这一点并将尝试重新排序独立(SASS)指令,以便读取后将跟随独立指令。

但是,一旦编译了代码,指令序列就不会改变(CUDA GPU当前不执行推测执行或无序执行)。因此,一旦取决于读取的操作发生在(SASS)指令流中,该线程将停止,直到读取操作完成。 (1)

因此,如果你做了这样的事情:

float a = global_data[idx];
float b = c*d;
a = a*b;

然后上面代码的第1行不会导致线程停顿。假设cd已准备好/可用,第2行不会导致失速。如果在遇到该行时尚未从全局内存中检索a的值,则第3行将导致停顿。 (因为它还取决于b,可能会有一些算术延迟 - 可能是一个停顿 - 而b正在通过乘法管道,但这个算术延迟可能比全局内存短得多延迟。)

如前所述,即使您不以这种方式编写代码,编译器通常也会尝试重新排序独立操作,以使情况更有利。例如,如果您以这种方式编写代码:

float b = c*d;
float a = global_data[idx];
a = a*b;

底层SASS代码很可能没有显着差异。即使你做了这样的事情:

float b = c*d;
float a = global_data[idx]*b;

编译器会将第二行代码分成(至少)两个独立的操作:global_data[idx]加载到寄存器中,然后进行乘法运算。同样,任何这些实现​​中的基础SASS代码可能没有实质性的不同。

(1)费米cc2.1和cc3.x以及更高的SM通常具有多个问题的能力,即。超标量操作。这意味着,对于相同的warp,来自同一指令流的多个(独立SASS)指令可以在资源限制和限制的同一周期中进行调度。我不认为这些多重案件与投机或执行的陈述相矛盾,我不认为这会对上述讨论产生实质性影响。一旦线程停止,即在指令调度器机制的范围内发出指令的机会已经“干涸”,那么在移除失速之前不能/将会安排进一步的指令。多发布机制的功能和限制的低级细节未发布AFAIK。

幻灯片14 here可能会引起关注。