一个CUDA程序包含了以下两个部分的混合:
1、在CPU上运行的主机代码
2、在GPU上运行的设备代码
NVIDIA的CUDA nvcc编译器在编译过程中将设备代码从主机代码中分离出来。主机代码是标准的C代码,使用C编译器进行编译。设备代码即核函数,是用扩展的带有标记数据并行函数关键字的CUDA C语言编写的,通过nvcc进行编译。
写一个CUDA C程序,你需要以下几个步骤:
1、用准用的扩展名.cu来创建一个源文件
2、使用CUDA nvcc编译器来编译程序
3、从命令行运行可执行文件,这个文件有可在GPU上运行的内核代码
使用GPU来编写一个"Hello World"程序:
#include <stdio.h>
//hello.cu
__global__ void helloWorld()
{
printf("Hello World from GPU\n");
}
int main()
{
printf("Hello World from CPU\n");
helloWorld <<<1,10>>>();
cudaDeviceReset();
return 0;
}
修饰符__global__告诉编译器这个函数将从CPU中调用,然后在GPU上执行。核函数必须有一个void返回类型。
<<< >>>里面的参数是执行配置,第一个值是网格维度,也就是启动块的数目。第二个值说明每个块使用多少线程来执行内核函数(块维度),这里表示有10个GPU线程会被调用。
同一个块中的线程可以互相协作。
有时候为了调试程序,可以将执行参数设置为<<<1,1>>>,模拟串行执行,可以用于验证结果是否正确。
cudaDeviceRest()用来显示地释放和清空当前进程中与当前设备有关地所有资源。
编译:
nvcc hello.cu -o hello
执行./hello
结果如下:
Hello World from CPU
Hello World from GPU
Hello World from GPU
Hello World from GPU
Hello World from GPU
Hello World from GPU
Hello World from GPU
Hello World from GPU
Hello World from GPU
Hello World from GPU
Hello World from GPU
如果NX没有设置过环境变量,那么直接使用nvcc编译会报错误,这里需要设置环境变量:
打开~/.bashrc ,添加环境变量如下:
export LD_LIBRARY_PATH=/usr/local/cuda/lib
export PATH=$PATH:/usr/local/cuda/bin执行source ~/.bashrc命令重新加载
CUDA编程结构:
1、分配GPU内存。
2、从CPU内存中拷贝数据到GPU内存。
3、调用CUDA内核函数来完成程序指定的运算。
4、将数据从GPU中拷回CPU内存。
5、释放GPU内存空间。
从CUDA6.0开始,NVIDIA提出了名为“统一寻址”的编程模型的改进,它连接了主机内存核设备内存空间,可使用单个指针访问CPU和GPU内存,无须彼此之间手动拷贝数据。