2016-02-25 74 views
0

什么时候执行从全局内存中读取的cuda线程(或整个warp),是否被调度程序置于睡眠状态?假设我在内核中进行一些计算,在读取内存之后,不依赖于读取的数据。这些可以在全局读取的数据不存在的时候执行吗?Cuda线程调度 - 延迟隐藏

回答

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正在通过乘法管道,但是这个算术延迟可能比全局内存延迟短得多)。

As已经提到过,即使你不这样编写代码,编译器通常会尝试重新排序独立操作,以使情况更加有利。例如,如果你用这种方式编写代码:

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)Fermi cc2.1和cc3.x及更高版本的SM通常具有多个问题的能力,即,超标量操作。这意味着对于相同的warp,来自相同指令流的多个(独立的SASS)指令可以按照资源限制和限制在相同的周期中进行调度。我不认为这种多重问题的情况与有关投机或OOO执行的言论相抵触,我认为这不会对上述讨论产生实质性影响。一旦线程停顿,即在指令调度程序机制的范围内发出指令的机会已经“干涸”,那么将不会安排进一步的指令,直到失速被移除为止。 AFAIK未发布多层次机制的能力和局限性的低层细节。

幻灯片14 here可能是感兴趣的。