CMake编译CUDA
- FindCUDA:在CMake 3.10版本已弃用。
- FindCUDAToolkit:在CMake 3.17版本更新。
使用CMake编译纯 .cu 文件
-
旧版本使用FindCUDA的CMake编写会比较麻烦,需要使用特定的cuda的函数,例如:
cuda_add_executable(test test.cu)
。 -
高版本使用FindCUDAToolkit的CMake编写极其简单,只需要指定语言:
enable_language(CUDA)
,其余一切与编译cpp相同。 -
例如,文件目录结构如下:
/project_root_path ----/build ----CMakeLists.txt ----main.cu
-
CMakeLists.txt内容如下:
cmake_minimum_required(VERSION 3.17) project(test) enable_language(CUDA) aux_source_directory(. SRC) add_executable(test ${SRC}) ## cd build ## cmake .. ## cmake --build .
-
可直接生成.exe文件
CMake混合编译
-
如果项目目录下既有.cu文件又有.cpp文件,先将
.cu
编译为动态库,再由.cpp
调用 -
目录结构:
/project_root_path ----/build ----/cuda --------CMakeLists.txt --------deploy.cu --------deploy.h ----CMakeLists.txt ----main.cpp
-
最外层
CMakeLists.txt
:cmake_minimum_required(VERSION 3.17) project(test) enable_language(CXX) add_subdirectory(./cuda) aux_source_directory(. SRC) add_executable(test ${SRC}) target_link_libraries(test gpu) ## 链接 gpu.lib 文件,不需要写绝对路径
-
cuda/CMakeLists.txt
:cmake_minimum_required(VERSION 3.17) project(gpu_lib) enable_language(CUDA) aux_source_directory(. SRC_CUDA) add_library(gpu SHARED ${SRC_CUDA}) ## 在Windows下,最后会编译出 gpu.dll 与 gpu.lib
-
编译一次即可同时生成
.exe
、.dll
和.lib
文件:cd build cmake .. cmake --build .
将编译出的
.dll
与.lib
移入.exe
的目录下即可调用 -
完整代码:
/** deploy.cu **/ #include <stdio.h> #include "deploy.h" __global__ void square(float* d_out, float* d_in){ int idx = threadIdx.x; float f = d_in[idx]; d_out[idx] = f * f; } int deploy(){ const int ARRAY_SIZE = 8; const int ARRAY_BYTES = ARRAY_SIZE * sizeof(float); float h_in[ARRAY_SIZE]; float h_out[ARRAY_SIZE]; for(int i = 0; i < ARRAY_SIZE; i++){ h_in[i] = float(i); } float* d_in; float* d_out; cudaMalloc((void**) &d_in, ARRAY_BYTES); cudaMalloc((void**) &d_out, ARRAY_BYTES); cudaMemcpy(d_in, h_in, ARRAY_BYTES, cudaMemcpyHostToDevice); square<<<1, ARRAY_SIZE>>>(d_out, d_in); cudaMemcpy(h_out, d_out, ARRAY_BYTES, cudaMemcpyDeviceToHost); for(int i = 0; i < ARRAY_SIZE; i++){ printf("%f", h_out[i]); if( i % 4 != 3 ) printf("\t"); else printf("\n"); } cudaFree(d_in); cudaFree(d_out); return 0; }
/* deploy.h */ #ifndef gpu_api #define gpu_api __declspec(dllexport) extern "C" gpu_api int deploy(); #endif
/* source.cpp */ #include "cuda/deploy.h" #include <iostream> using namespace std; #pragma comment(lib, "gpu.lib") int main(){ deploy(); return 0; }
NVCC的编译平台报错
-
使用MSVC时,默认的编译平台是WIN 32
-
CMake使用默认编译平台nvcc可能会报错:
nvcc fatal: 32 bit compilation is only supported for Microsoft Visual Studio 2013 and earlier
-
可以通过以下命令改变:
cmake .. -G "Visual Studio 15 2017 Win64"
-
在指定编译平台后,就可以正常使用MSVC编译cuda代码了。
-
如果不想输入命令,可以直接新建
环境变量
,命名为:CMAKE_GENERATOR
,值为Visual Studio 15 2017 Win64
。 -
也有其他方法,比如在
CMakeLists.txt
中添加set(CMAKE_GENERATOR "Visual Studio 15 2017 Win64")
。但是经过个人实践,在只有一个CMakeLists.txt时,该方法无效,因为在读取到这一条语句之前就已经选定编译平台了。
使用VS启动项目
- 因为使用MSVC编译的,所以会生成VS的解决方案(
.sln
文件),直接用VS运行即可。 - 可能会出现:
无法启动.../ALL_BUILD,拒绝访问
的问题,这是因为CMake编译出的项目太多了,设置一个启动项即可解决。(右键项目 – 属性 – 设置为启动项)
使用VS调试CUDA
- 需要给
nvcc
添加-G
选项,在旧版本的FindCUDA中可以使用set(CUDA_NVCC_FLAGS -G;-g)
添加调试选项,但是在新版的FindCUDAToolkit中CUDA_NVCC_FLAGS被弃用了,这样写是无效的,更换为了更通用的add_definitions("-g -G")
。
-
在CMakeLists.txt中添加add_definitions:
cmake_minimum_required(VERSION 3.17) project(test) enable_language(CUDA) aux_source_directory(. SRC) add_definitions("-g -G") add_executable(test ${SRC})
-
可以观察到编译选项中增添了
-G
选项:
- 启动
Nsight Monitor
:开始菜单中或者直接搜索可以找到该程序。
-
右下角会有Nsight Monitor的图标,右键,选择
Options
进行简单配置。General
中Enable Secure Connection
设置为True
CUDA(Legacy)
中Use This Monitor For CUDA Attach
设置为True
-
使用
.sln
文件启动VS,并设置项目为启动选项。 -
资源管理器中右键项目,选择
Nsight User Properties
-
将
Launch
中的Launch external program
设置为生成的exe文件
-
打断点,选择VS菜单中的
Nsight
,选择Start CUDA Debugging
,至于是选用legacy
还是Next-Gen
需要看你的GPU架构,我的架构不支持Next-Gen
,只能选用Legacy
。Legacy
只支持调试GPU代码Kernel函数,Next-Gen
两者都能调试。
-
然后就可以调试了。
参考文献
.cu
文件动态库编写教学参考自:https://blog.csdn.net/weixin_40106401/article/details/101352609- CMake FindCUDAToolkit编译
.cu
示例:https://nanxiao.gitbooks.io/cuda-little-book/content/posts/use-cmake-to-compile-cuda-program.html - NVCC编译平台报错问题解决参考自:https://stackoverflow.com/questions/50474695/cuda-with-cmake
- 无法启动…/ALL_BUILD,拒绝访问的问题https://blog.csdn.net/qq_38977019/article/details/90239301