CUDA C++编程指南
1.1 使用GPU的好处
图形处理单元(GPU)在类似的价格和功率范围内提供比CPU高得多的指令吞吐量和存储器带宽。许多应用程序利用这些更高的功能在GPU上比在CPU上运行得更快(请参阅GPU应用程序)。其他计算设备,如FPGA,也非常节能,但提供的编程灵活性远低于GPU。
GPU和CPU之间的这种能力差异是因为它们在设计时考虑到了不同的目标。虽然CPU被设计成擅长以尽可能快的速度执行一系列被称为线程的操作,并且可以并行执行几十个这样的线程,但GPU被设计成善于并行执行数千个这样的操作(将较慢的单线程性能均衡以实现更大的吞吐量)。
GPU专门用于高度并行的计算,因此设计为使更多的晶体管用于数据处理,而不是数据缓存和流控制。下图显示了CPU与GPU的芯片资源分布示例。
将更多的晶体管用于数据处理,例如浮点计算,对于高度并行的计算是有益的;GPU可以通过计算隐藏存储器访问延迟,而不是依赖于大型数据缓存和复杂的流控制来避免长的存储器访问延迟(这两者在晶体管方面都是昂贵的)。
通常,应用程序混合了并行部分和顺序部分,因此系统设计时混合了GPU和CPU,以最大限度地提高整体性能。具有高度并行性的应用程序可以利用GPU的这种大规模并行特性来实现比CPU更高的性能。
1.2 CUDA:通用并行计算平台和编程模型
2006年11月,NVIDIA推出了CUDA,这是一个通用的并行计算平台和编程模型,它利用NVIDIA GPU中的并行计算引擎,以比CPU更高效的方式解决许多复杂的计算问题。
CUDA提供了一个软件环境,允许开发人员使用C++作为高级编程语言。如下图所示,支持其他语言、应用程序编程接口或基于指令的方法,如FORTRAN、DirectCompute、OpenACC。
1.3 可扩展的编程模型
多核CPU和多核GPU的出现意味着主流处理器芯片现在是并行系统。挑战在于开发透明地扩展并行度以利用不断增加的处理器核心数量的应用软件,就像3D图形应用程序透明地扩展其并行度以使用大量不同核心数量的GPU一样。
CUDA并行编程模型旨在克服这一挑战,同时为熟悉C等标准编程语言的程序员保持较低的学习曲线。
它的核心是三个关键的抽象——线程组的层次结构、共享内存和屏障同步——它们只是作为一组最小的语言扩展暴露给程序员。
这些抽象提供了细粒度的数据并行性和线程并行性,嵌套在粗粒度的数据并行度和任务并行度中。它们指导程序员将问题划分为粗的子问题,这些子问题可以由线程块并行独立解决,每个子问题划分为更精细的部分,这些部分可以由块内的所有线程并行协同解决。
这种分解通过允许线程在解决每个子问题时进行协作来保持语言的表达性,同时实现自动可伸缩性。事实上,每个线程块都可以在GPU内的任何可用多处理器上以任何顺序、并发或顺序进行调度,因此编译后的CUDA程序可以在任何数量的多处理器上执行,如下图所示,并且只有运行时系统需要知道物理多处理器计数。
这种可扩展的编程模型允许GPU架构通过简单地扩展多处理器和内存分区的数量来跨越广泛的市场范围:从高性能爱好者GeForce GPU和专业的Quadro和Tesla计算产品到各种廉价的主流GeForce GPU(请参阅CUDA启用的GPU以获取所有CUDA启用GPU的列表)。
GPU是围绕流式多处理器(SM)阵列构建的(有关更多详细信息,请参阅硬件实现)。多线程程序被划分为相互独立执行的线程块,因此多处理器数量多的GPU将比多处理器数量少的GPU在更短的时间内自动执行程序。