CUDA的动态并行化支持是通过对CUDA编程模型的扩展实现的,扩展的CUDA编程模块使CUDA kernel可以创建和同步新的工作。基本上,一个子CUDA kernel可以由一个父CUDA kernel调用,然后在该子CUDA kernel 任务完成的时候进行同步操作。父CUDA kernel可以使用子CUDA kernel的操作结果,所有这一切无需CPU的干预。
此外,CUDA编程模型中还支持递归,一个CUDAkernel可以调用它自己。
CUDA的执行模块基于原语的线程、线程块以及网格,使用kernel 函数定义对单个线程在线程块和网格中的操作。当一个kernel函数被调用,网格的特性由执行配置来描述,在CUDA的C语言中有特定的语法。CUDA的动态并行化对已经运行在一个网格中的线程来说,扩展了配置和启动网格的能力,以及等待网格操作的结束。
通过使用CUDA的动态并行技术,先前的算法和程序需要修改,以消除递归、不规则循环、或者其他之类的不适合并行化的设计,修改为显示的并行化表达形式。程序流控制可由一个CUDA kernel控制完成,减少由Kernel发起的GPU和CPU之间的数据传输。
动态并行化的实现——父子网格
正在执行的网格中的一个线程配置并启动一个新的网格,该新网格属于父网格(配置和启动新网格的线程所在的网格),线程新创建的网格称为子网格。父网格创建子网格的操作是CUDA动态并行化的具体实现。
子网格的发起和完成是合理嵌套的,意味着父网格直到其创建的所有子网格都完成才能完成工作,也就是父子网格之间必须要保证操作的同步性。Runtime保证了父子间的隐式的同步,即使启动新网格的线程在启动新网格时没有明确地同步子网格。
子网格的Kernel可能也会发起自己的工作,创建一个新的网格。发起操作可以持续的代数最大达到24代,但是一般受限于资源,达不到这个代数。所有子网格发起的工作必须按顺序完成。如下的图中,Kernel C 直到Kernel Z执行完成之后才能执行。