Writing Application Code for the GPU¶
CUDA 为许多常用编程语言提供扩展,而在本实验中,我们将会为 C/C++ 提供扩展。这些语言扩展可让开发人员在 GPU 上轻松运行其源代码中的函数。
以下是一个 .cu
文件(.cu
是 CUDA 加速程序的文件扩展名)。其中包含两个函数,第一个函数将在 CPU 上运行,第二个将在 GPU 上运行。请抽点时间找出这两个函数在定义方式和调用方式上的差异。
void CPUFunction()
{
printf("This function is defined to run on the CPU.\n");
}
__global__ void GPUFunction()
{
printf("This function is defined to run on the GPU.\n");
}
int main()
{
CPUFunction();
GPUFunction<<<1, 1>>>();
cudaDeviceSynchronize();
}
以下是一些需要特别注意的重要代码行,以及加速计算中使用的一些其他常用术语:
__global__ void GPUFunction()
-
__global__
关键字表明以下函数将在 GPU 上运行并可全局调用,而在此种情况下,则指由 CPU 或 GPU 调用。 - 通常,我们将在 CPU 上执行的代码称为主机代码,而将在 GPU 上运行的代码称为设备代码。
- 注意返回类型为
void
。使用__global__
关键字定义的函数需要返回void
类型。
GPUFunction<<<1, 1>>>();
- 通常,当调用要在 GPU 上运行的函数时,我们将此种函数称为已启动的核函数。
- 启动核函数时,我们必须提供执行配置,即在向核函数传递任何预期参数之前使用
<<< ... >>>
语法完成的配置。 - 在宏观层面,程序员可通过执行配置为核函数启动指定线程层次结构,从而定义线程组(称为线程块)的数量,以及要在每个线程块中执行的线程数量。稍后将在本实验深入探讨执行配置,但现在请注意正在使用包含
1
线程(第二个配置参数)的1
线程块(第一个执行配置参数)启动核函数。
cudaDeviceSynchronize();
- 与许多 C/C++ 代码不同,核函数启动方式为异步:CPU 代码将继续执行而无需等待核函数完成启动。
- 调用 CUDA 运行时提供的函数
cudaDeviceSynchronize
将导致主机 (CPU) 代码暂作等待,直至设备 (GPU) 代码执行完成,才能在 CPU 上恢复执行。
网友评论