什么是cuda线程(或整个warp),执行从全局内存读取,由调度程序进入睡眠状态?假设我在内核读取后立即在内核中进行了一些计算,这些计算不依赖于读取数据。可以在全局读取的数据还没有的时候执行吗?
答案 0 :(得分:1)
读取的内存本身不会导致停顿(除非LD / ST单元不可用)。
当另一个操作需要使用该存储器读操作的结果时,将发生线程停止。
编译器知道这一点并将尝试重新排序独立(SASS)指令,以便读取后将跟随独立指令。
但是,一旦编译了代码,指令序列就不会改变(CUDA GPU当前不执行推测执行或无序执行)。因此,一旦取决于读取的操作发生在(SASS)指令流中,该线程将停止,直到读取操作完成。 (1)
因此,如果你做了这样的事情:
float a = global_data[idx];
float b = c*d;
a = a*b;
然后上面代码的第1行不会导致线程停顿。假设c
和d
已准备好/可用,第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可能会引起关注。