CUDA用GPU输出Hello World

用GPU输出Hello World

1.检查环境

学习一个新编程语言的最好方式就是使用这种语言来编写程序。在本节,你将开始编写在GPU上运行的第一个内核代码。像其他任何编程语言一样编写GPU上的第一个程序是输出字符串“Hello World”。

如果这是你第一次使用CUDA,在Linux系统中,你可以想使用以下命令来检查CUDA编译器是否正确安装:

1
which nvcc

通常的结果可能是

1
/usr/local/cuda/bin/nvcc

你还需要检查你的机器上是否安装了GPU加速卡。对吃你可以在Linux系统上使用以下命令:

1
ls -l /dev/nv*

通常的结果是:

image-20230116170920773

在这个例子中,你发现了两个GPU卡(不同的用户配置可能有所不同,因此显示结果会有所差异)。

2.第一个CUDA C程序

现在你要准备好写你的第一个CUDA C程序。写一个CUDA C程序,你需要以下几个步骤:

  1. 用专用扩展名.cu来创建一个源文件。
  2. 使用CUDA nvcc编译器来编译程序。
  3. 从命令行运行可执行文件,这个文件有可在GPU上运行的内核代码。

首先,我们编写一个C语言程序来输出“Hello World”,如下所示:

1
2
3
4
5
#include <stdio.h>
int main(){
printf("Hello World from CPU!\n");
return 0;
}

把代码保存到hello.cu中,然后使用nvcc编译器来编译。CUDA nvcc编译器和gcc编译器及其他编译器有相似的语义

1
nvcc hello.cu -o hello

如果你运行可执行文件hello,将会输出:

1
Hello World from CPU!

接下来,编写一个内核函数,命名为helloFromGPU,用它来输出字符串“Hello World from GPU!”。

1
2
3
__global__ void helloFromGPU(void){
printf("Hello World from GPU!\n");
}

修饰符__global__告诉编译器这个函数将会从CPU中调用,然后在GPU上执行。用下面代码启用内核函数。

1
helloFromGPU<<<1,10>>>();

三重尖括号意味着从主线程到设备端代码的调用。一个内核函数通过一组线程来执行,所有线程执行相同的代码。三重尖括号里面的参数是执行配置,用来说明使用多少线程来执行内核函数。在这个例子中,有10个GPU线程被调用。综上所述,得到代码清单1-1所示的程序。

3.代码清单1-1Hello World from GPU! (hello.cu)

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
__global__ void helloFromGPU(void){
printf("Hello World from GPU!\n");
}
int main(){
//hello from cpu
printf("Hello World from CPU!\n");


helloFromGPU<<<1,10>>>();
cudaDeviceReset();
return 0;
}

函数cudaDeviceRest()用来显式地释放和清空当前进程中与当前设别有关的所有资源。如下所示,在nvcc命令行中使用-arch sm_20进行编译:

1
nvcc -arch sm_20 hello.cu -o hello

开关语句-arch sm_20使编译器为Fermi架构生成设备代码。运行这个可执行文件,它将输出10条字符串“Hello World from CPU!”,每个线程输出一条。

image-20230116173446169

4.一个典型的CUDA编程结构包括5个主要步骤

  1. 分配GPU内存
  2. 从CPU内存中拷贝数据到GPU内存
  3. 调用CUDA内核函数来完成程序指定的运算
  4. 将数据从GPU拷回CPU内存
  5. 释放GPU内存空间

在hello.cu中,你只看到了第三步:调用内核。

5.参考资料

CUDA C编程权威指南 程润伟,Max Grossman(美),Ty Mckercher


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!