GPU架构和CUDA架构
1、CPU和GPU的硬件结构和架构
CPU具有复杂的控制硬件和较少的数据计算硬件,复杂的控制硬件在性能上提供了CPU的灵活性和一个简单的编程接口,但就功耗而言,这是昂贵的。GPU具有简单的控制硬件和更多的数据计算硬件,使其具有并行计算的能力,这种结构使得它更节能。
一般来说任何硬件架构的性能都是根据延迟和吞吐量来度量的。延迟是完成给定任务所花费的时间,而吞吐量是在给定时间内完成任务的数量。这两个概念并不矛盾,通常情况下提高一个,另一个也会随之提高。在某种程度上,大多数硬件架构旨在提高延迟或吞吐量。比如,从一个地方到240公里以外的另一个地方。你可以开一辆容纳5人的汽车,时速60公里,或者开一辆能容纳40人的公交车,时速40公里。汽车单次只需要花费4个小时,延迟比公交车的单次6小时更低,但平均每小时只能输送1.2人,而公交车平均每小时可以输送6.66人,吞吐量更高。
正常的串行CPU被设计为优化延迟,而GPU被设计为优化吞吐量。要想在相同的钟速度和功率要求下提高计算性能,可以通过并行计算。GPU通过许多简单的计算单元并行工作来提供这种能力。为了与CPU交互,并利用其并行计算能力,需要一个由CUDA提供的并行编程架构。
2、CUDA构架
所有的GPU都有许多被称为核心(Core)的并行处理单元。在硬件方面,这些核心被称为流处理器和流多处理器。GPU有这些流多处理器的网格。在软件方面,CUDA程序是作为一系列并行运行的多线程(Thread)来执行的。每个线程都在不同的核心上执行。可以将GPU看作多个快(Block)的组合,每个块可以执行多个线程。每个块绑定到GPU上不同的流多处理器。
称CPU及内存为主机(Host),GPU及其内存称为设备(Device)。CUDA代码包含主机和设备代码。只是这段代码是在大量内核上并行执行的。
CUDA C程序的开发步骤如下:
1)为主机和设备显存中的数据分配内存;
2)将数据从主机内存复制到设备显存;
3)通过指定并行度来启动内核;
4)所有线程完成以后,将数据从设备显存复制会主机内存
5)释放主机和设备上使用的所有内存。
3、一个基本的CUDA C程序
#include<iostream> __global__ void myfirstkernel(void) { } int main(void) { myfirstkernel << <1, 1 >> > (); printf("Hello, CUDA!\n"); return 0; }
__global__是CUDA C在标准C中添加的一个限定符,它告诉编译器在这个限定符后面的函数定义应该在设备上而不是在主机中运行。main函数没有被global关键字修饰,因此main函数将在主机上运行。
对于空的myfirstkernel函数的调用有一些尖括号和数值表示:从主机代码调用设备代码,称为内核调用。数字表示块的数量和将在设备上并行运行的线程数。上面的例子中<< <1, 1 >> >表示myfirstkernel将在设备上第一个块和一个线程或块上。