GPU的架构和编程原理
在CUDA的架构下,一个程序分为两个部分:Host端和Device端。Host端是指在CPU上执行的部分,而Device端则是在显示芯片上执行的部分。Device端的程序又称为“Kernel"。通常Host端程序会将数据准备好后,复制到显卡的内存中,再由显示芯片执行Device端程序,完成后再由Host端程序将结果从显卡的内存中取回。
在CUDA架构下,显示芯片执行时的最小单位是线程(Thread)。数个线程可以组成一个块(Block)。一个块中的线程能存取同一块共享的内存,而且可以快速进行同步的动作。
每一个Block所能包含的Thread数目是有限的。不过,执行相同程序的Block,可以组成网格(Grid)。不同Block中的Thread无法存取同一个共享的内存,因此无法直接互通或进行同步。因此,不同Block中的Thread能合作的程度是比较低的。不过,利用这个模式,可以让程序不用担心显示芯片实际上能同时执行的Thread数目限制。例如,一个具有很少量执行单元的显示芯片,可能会把各个Block中的Thread顺序执行,而非同时执行。不同的Grid则可以执行不同的程序(即Kernel).
每个,bread都有自己的一份寄存器(Register)和本地存储(Local Memory)的空间。同一个Block中的每个thread则有共享的一份共享存储(Share Memory)。此外,所有的Thread(包括不同Block的Thread)都共享一份 Global Memory、静态存储(Constant Memory)和纹理存储(Texture Memory)。不同的Grid则有各自的Global Memory、Constant Memory和Texture Memory。
在编写程序时,通过cuda编译器来指定处理器进行并行计算,能够最大限度地增加并行数,进而提高处理能力。Grid、Block和Thread的关系如图16-2所示。
图16-2 CUDA的资源组织形式