并行计算与代码测试:原理、性能与实践
1. 并行计算中的CUDA编程
1.1 执行配置与块大小选择
在CUDA编程里,下一步要做的是通过设定CUDA网格(line 222)和CUDA块(line 223)的维度,来告知CUDA执行配置。我们选用32 × 16的块大小,这是因为计算能力为3.5的NVIDIA GPU每个块最多支持1024个线程,每个多处理器最多支持2048个线程。当然,我们也能自由选择其他块大小,例如16 × 16。建议程序员尝试不同的块大小,以此来优化性能。在我们的例子中,32 × 16(512个线程)的执行速度比16 × 16(256个线程)稍快。网格维度是依据有限差分网格大小计算得出的,公式为N_BLOCKS_X = NX / N_THREADS_X和N_BLOCKS_Y = NY / N_THREADS_Y。需注意,网格在x、y和z方向的最大维度分别为2,147,483,647 × 65,535 × 65,535。
1.2 内核调用与内存管理
接着,我们使用尖括号语法(<<<…>>>)调用内核函数solveWaveGPU,如line 227所示。在CUDA术语中,在GPU上执行的函数被称作内核。每次时间迭代后,在主机端交换设备内存的指针,这和串行版本的编程方式十分相似。要注意,我们通过交换指针将数据保留在设备上。
在Listing 16.4b所示的内核solveWaveGPU中,我们给函数添加__global__标识符,以此告知编译器该函数将在GPU上执行。要注意,__global__标识符和设备上的全局内存并无关联。我们保留了串行版本中的有限差分公式(lines 73–74