Volta架构下新增加的一个特性——独立线程调度机制。
独立线程调度机制可以这样理解,主要是为线程与线程之间的通信和同步提供更加灵活的方式。
GPU中的线程执行实际上是以WARP为基本单元执行的,每个warp包含32个线程,这32个线程拥有共同的程序计数器,叫做Program Counter,还有Stack(堆栈)。无论程序是否出现分支,32个线程在同一个时刻都要执行相同的指令。
比如上图这样的一段代码,用现成ID号来定义程序的分支。我想让0到3号执行A、B指令,其他线程去执行X、Y指令。执行过程就像右图中所示,首先0到3号线程会去执行A、B指令,但同时其他线程会处于空跑的状态。接下来其他线程去执行X、Y指令,而0到3号线程处于空跑状态。所以说整个指令执行完毕的时间,实际上是A、B、X、Y四个指令的执行时间之和。这就是我们通常讲的,在WARP内出现分支时的执行时间轴。
如果我需要在A指令与X指令执行之后,进行一个线程之间的同步通信,例如线程从0到3执行指令B时需要利用指令X的执行结果,而这种算法在Pascal架构下是没有办法实现的。
在Volta架构下,NVIDIA改变了这种线程调度机制。每一个线程可以有自己独立的程序计数器PC以及堆栈,这使得每个线程可以独立进行线程的调度。
在我们所举的例子里,执行指令B之前需要新同步通信得到A和X的结果。我们可以在A指令和X指令执行之后,进行一个WARP内的同步。NVIDIA在CUDA9里面新增加的一个函数——syncwarp,这样就改变了指令的执行顺序。可以看右边的图,此时变成了什么呢?首先线程0到3去执行指令A,然后其他的线程去执行指令X,接下来0到3再去执行指令B,最后是其他线程再去执行指令Y。需要注意的是,此时在这个分支的外部,我们还需要再进行显式的syncwarp的线程同步的声明。