随着科技的发展,计算机已经成为我们身边不可缺少的一部分。追求效率是发展的趋势,然而基于CPU的串行代码在某些场景下的运行效率难以满足科研或生产的需求,Nvidia推出的CUDA可以解决部分问题。接下来我们就可以开始主要的内容——CUDA并行计算。
异构计算主要是指使用不同类型指令集和体系架构的计算单元组成系统的计算方式。
如上图所示,有CPU与GPU两个计算单元。下图术语是在后面会经常提到的Host与Device。
CUDA程序的编写即为串行代码与并行代码的结合,串行代码在CPU端执行,并行代码在GPU端运行。
第一步,我们先将输入的数据从CPU内存复制到GPU的显存当中。
第二步,在执行芯片上缓存数据,计算数据。
第三步,将GPU中计算好的结果传回CPU中。
注意,在CUDA程序的编写中,__global__必须有void返回类型且不能与__device__或__host__声明符一起使用的,__global__函数的调用是异步的。__device__在设备上执行且只能从设备调用,__host__在主机上执行且只能从主机调用,这两个声明符可以一起使用,代表此函数是为主机和设备编译的。
__global__定义的kernel函数在CPU上调用,在GPU中执行,切记必须返回void。
我们来看一个很简单的CUDA程序,首先我们用__global__声明符定义一个kernel函数 Vecadd,计算两个数组之和。然后在main中调用核函数,<<<x,y>>>中的x,y代表调用的线程。
CUDA程序的编译,首先在C++的预处理器中将代码分为两部分,上图绿色虚线框内左侧为C++编译过程,绿色实线框中为GPU的编译过程。
上图为一个简单CUDA程序编译的例子,首先在hello_from_gpu.cuh文件中声明hello_from_gpu函数,在hello_from_gpu.cu文件中实现函数,在hello_from_gpu_main.cu文件中编译。
最后贴出课上写的入门代码。
此处cudaDeviceSynchronize()十分重要,该方法将停止CPU端线程的执行,直到GPU端完成之前CUDA的任务,包括kernel函数、数据拷贝等。(kernel function)kernel函数是异步执行的,也就是说,kernel函数在调用之后立即把控制权交换给CPU,CPU接着往下执行。所以我们需要同步Host与Device。
#include <stdio.h>
__global__ void hello_from_gpu()
{
printf("Hello World from the GPU!\n");
}
int main(void)
{
hello_from_gpu<<<2, 4>>>();
cudaDeviceSynchronize();
return 0;
}
接下来我还会继续将后续的学习心得发出,本文基于Nvidia Summer Camp所提供的资源加上个人的一些浅显的理解而写,需要学习的地方还很多,如果有写的不好的或者不对的地方欢迎大家指正!谢谢!