CUDA(Compute Unified Device Architecture)是由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题。使用CUDA开发编程,可以使运算速度提升,相比较于CPU,GPU的并行计算架构更适合处理机器学习这样的大批量运算工作。NVIDIA也提供了CUDA工具包,供开发者们使用学习。
个人认为学好CUDA的前提是算法基础,在基础牢固的前提下,由串行编程思维转换为并行思维,CUDA可以为你的程序进行提速。相反,缺失算法基础而接触CUDA开发,将无法很好地利用CUDA的优势,只会导致“良莠不分”的情形。废话不多说,下面直接开搞。
注意:本篇所讲述的环境配置仅仅是一种运行方法,而实际搭建时往往会有很多方法。本篇所述方法仅作参考。
一、准备所需工具、软件
Visual Studio 2022:https://visualstudio.microsoft.com/zh-hans/downloads
CMake:https://cmake.org/download
CLion:https://www.jetbrains.com/clion/download
CUDA工具包:https://developer.nvidia.com/cuda-11-7-0-download-archive
本篇使用11.7版本CUDA工具包,以和cuDNN搭配使用。如欲使用最新版本CUDA工具包开发,请点击链接下载。当然也要注意你当前的NVIDIA驱动版本是否支持该版本的CUDA,在控制台中输入以下命令,在Driver Version内查看你的驱动版本。版本对照表点击此处链接查看。
nvidia-smi
然后注意一下CLion这个软件,下载后只会给你30天试用。但如果在官网使用校园邮箱等方式来进行验证,即可以学生身份免费使用JetBrains全家桶。JetBrains学生认证通道请点击此处链接。
二、安装、配置工具及软件
注意:版本根据个人需求选择。如果你已经拥有以上的某种工具,可以跳过安装。但如果你的设备先安装的CUDA,而后安装的Visual Studio,则会在使用CMake编译时引起No CUDA toolset found的报错。具体解决方法可以点击此处参考这篇文章。
2.1 安装Visual Studio 2022
本篇对Visual Studio 2022的安装方式不具体展开叙述,这里只展示必要的部分,具体安装方法可以参考其他平台的教程。注意勾选相应的开发方法,以及MSVC。最后有必要的话记得更改一下安装路径。
2.2 安装CMake
打开官方下载网站后,建议下载msi安装文件。因为使用安装文件可以自动为你添加CMake的环境变量,十分方便。直接打开CMake安装包即可,但添加环境变量的选项是手动勾选的,请注意这一点。
2.3 安装CLion
和其他编译器一样,下载安装包后打开,直接根据自己的需要勾选并安装即可。这里不做过多叙述。
2.4 安装CUDA
安装CUDA时,会提示你将安装包解压的文件暂时放到哪个路径,而非实际安装路径。一般直接使用默认路径即可。CUDA安装时会检查你的设备环境,如果之前安装过CUDA,则需要重新卸载安装。卸载内容包括CUDA和Nsight一系列内容。
2.5 检查是否安装正确
除了使用Visual Studio 2022和CLion创建一个简单的测试工程,看看能否正常使用“Hello world!”程序以外,也要在控制台中检查一下CMake与CUDA是否安装成功。在控制台内输入以下指令。注意输入nvcc时会出现fatal报错,这是因为使用nvcc时没有参数。只要控制台能执行指令即可。
cmake
nvidia-smi
nvcc
三、在实例中进行配置
3.1 写一个简单的CUDA代码(hello_world.cu)
万事俱备,只欠东风。我们既然已经搭建好了所需的环境,那我们先来写一个简单的CUDA代码试运行一下。CUDA的运行代码后缀是.cu,使用nvcc来编译运行。首先我们创建一个hello_world.cu文件,编辑其内容如下:
#include<cstdio>
__global__ void hello_world()
{
printf("GPU: Hello world!\n");
}
int main()
{
printf("CPU: Hello world!\n");
hello_world<<<1,10>>>();
cudaDeviceReset(); // 确保刷新资源并整理输出
system("pause");
return 0;
}
这个代码都做了什么?首先我们定义了一个CUDA核函数(Kernel)——hello_world()。核函数使用__global__限定符声明,表明它可以从主机(CPU)代码中调用,并在设备(GPU)上并行执行。这里hello_world()的作用是打印一条消息。__global__可以看作是GPU指令运行的主函数。
在main函数里,我们首先用CPU打印一条消息,使用CPU执行的指令和正常C语言写法相同。之后我们调用hello_world核函数,使用使用<<<1,10>>>
语法指定启动配置,这个语法意味着什么?
其中,1表示启动1个块,10表示每个块中有10个线程。因此,核函数hello_world将在GPU上并行执行10次,而这10次运行是在GPU上并行实现的。具体并行方式涉及到GPU架构问题,我们放到下一篇再展开叙述。
3.2 使用nvcc运行hello_world.cu
打开cmd命令行窗口,使用cd指令,将目录转移到hello_world.cu所在文件夹,并使用以下指令来使用nvcc编译hellow_world.cu:
nvcc -o hello_world hello_world.cu
这条命令告诉nvcc,将hello_world.cu编译成名为hello_world.exe的可执行文件。同时也可以通过添加其他编译选项来自定义编译过程,例如指定架构或优化级别等。生成hellow_world.exe后打开,即可运行编译好的hello_world.cu程序。
往往小型的测试项目直接使用nvcc编译是没问题的,但面对稍微大一点的项目,我们便使用CMake来编译和运行CUDA文件。CMake提供了一种更灵活、可扩展的方式来管理复杂项目的构建过程。特别是对于涉及多个文件、依赖关系和不同编译器选项(如CUDA项目)的情况,CMake可以简化构建配置,确保在不同平台和环境下的一致性。CMake可以自动检测编译器、库和工具,生成适用于特定平台的构建系统(如CLion项目或Visual Studio解决方案)。接下来,我们使用CMake和CLion来进行CUDA的进一步开发。
四、配置CLion
4.1 Toolchains工具链
注意:CUDA开发是不支持Ming64作为工具链的,我们要将其默认的Ming64改为Visual Studio。直接在CLion里进行设置就行了。可以看到作为default的Ming64已经被删掉了。
4.2 CMake
CLion会自动检测CMake并配置的。如果编译时出现了问题,可以根据下图检查一下CMake是否配置正确。
五、编写CMake文件
CMake是一个免费的多平台编译工具,旨在构建、测试和软件打包。CMake是用于控制软件使用简单的平台和编译器编译过程独立配置文件。在一些大型项目中,CMake扮演了向导的角色,目的是实现软件构建流程的自动化,并且是跨平台的。
负责了解如何编写CMake文件前,我们要先知道为什么使用CMake。原因很简单,CUDA开发库是十分庞大的,我们要使用CMake确保开发环境可编译,以便使用C语言开发。
在拥有CMake的环境下,我们在CLion新建一个untitled的Project,可以发现其自动生成了一个CMakeLists.txt,其内容如下:
cmake_minimum_required(VERSION 3.27)
project(untitled)
set(CMAKE_CXX_STANDARD 17)
add_executable(untitled main.cpp)
里面包含了一些工程的基础信息,包括CMake的版本、项目的名称、使用的标准以及添加执行的信息。我们的最终目标不是运行.cpp文件,而是执行CUDA文件。我们创建一个test.cu文件,并对CMakeLists.txt文件进行一些简单的改动,其中加粗部分是改动的内容:
cmake_minimum_required(VERSION 3.27)
project(untitled CXX C CUDA)
set(CMAKE_CXX_STANDARD 17)
add_executable(untitled test.cu)
我们为项目指定了使用哪些语言(CXX=GCC),并将test.cu加入到了执行。
六、在CLion中编写CUDA代码
在test.cu内编写以下内容:
#include<cstdio>
__global__ void hello_world()
{
printf("GPU: Hello world!\n");
}
int main()
{
printf("CPU: Hello world!\n");
hello_world<<<1,10>>>();
cudaDeviceReset();
return 0;
}
之后进行编译,成功。至此我们搭建了CLion中使用CUDA的环境。