基于CMake的现有C++项目添加CUDA代码的实现指导求助
在CMake构建的C++项目中添加CUDA代码(支持单独编译)
嘿,我完全懂你现在的处境——刚上手CMake,想把CUDA代码塞进已有的C++项目里,参考了NVIDIA那篇讲单独编译的文章但人家用的是Make,自己折腾半天没搞定对吧?别着急,我来一步步给你讲清楚CMake里怎么实现对应的功能,帮你把CUDA代码无缝集成进去。
一、先让CMake认出来CUDA
CMake从3.8版本开始对CUDA的支持就很成熟了,首先得在项目里开启CUDA支持,有两种简单方式:
- 方式一:创建项目时直接指定支持的语言,把CUDA加进去:
cmake_minimum_required(VERSION 3.8 FATAL_ERROR) project(YourProjectName LANGUAGES CXX CUDA)
- 方式二:如果已经写了
project指令,也可以单独开启:
enable_language(CUDA)
(不推荐用旧版的find_package(CUDA),那是CMake 3.8之前的老方法了)
二、配置CUDA单独编译(对应NVIDIA文章里的Make逻辑)
NVIDIA那篇文章的核心是开启CUDA的单独编译(Relocatable Device Code),在CMake里我们可以通过编译选项来实现:
- 指定GPU架构:先给CMake明确你的GPU架构,比如
sm_75(对应Turing系列显卡),避免自动检测出错:
set(CMAKE_CUDA_ARCHITECTURES 75) # 根据你的GPU型号改,比如35、52、61、80这些都可以
- 开启单独编译:关键就是加
-rdc=true这个选项,你可以全局设置,也可以针对单个目标设置(更推荐后者,灵活):
# 全局设置(所有CUDA文件都生效) set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -rdc=true") # 或者针对特定目标设置(更推荐) target_compile_options(YourTargetName PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-rdc=true>)
三、把CUDA源文件加进项目
这一步很简单,把你的.cu源文件和C++的.cpp文件一起加到可执行文件或库目标里就行:
# 比如你的C++主文件是main.cpp,CUDA内核文件是my_kernel.cu add_executable(MyProjectExec src/main.cpp src/my_kernel.cu ) # 如果是静态/动态库的话,用add_library # add_library(MyProjectLib STATIC src/my_kernel.cu src/utils.cpp)
四、处理头文件和链接
- 头文件目录:如果你的CUDA头文件(
.cuh)在单独的目录,比如include,记得让CMake找到它:
target_include_directories(MyProjectExec PRIVATE include)
- 链接CUDA库:大部分情况下CMake会自动链接CUDA运行时库(
cudart),但如果遇到链接错误,可以显式指定:
target_link_libraries(MyProjectExec PRIVATE CUDA::cudart)
五、完整的示例CMakeLists.txt
给你一个可以直接参考的完整示例,你可以照着改自己的文件:
cmake_minimum_required(VERSION 3.8 FATAL_ERROR) project(CudaCppDemo LANGUAGES CXX CUDA) # 设置GPU架构,根据你的显卡调整 set(CMAKE_CUDA_ARCHITECTURES 75) # 设置C++和CUDA的标准,确保兼容 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CUDA_STANDARD 17) set(CMAKE_CUDA_STANDARD_REQUIRED ON) # 开启CUDA单独编译 target_compile_options(CudaCppDemo PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-rdc=true>) # 添加源文件 add_executable(CudaCppDemo src/main.cpp src/vector_add.cu ) # 包含头文件目录 target_include_directories(CudaCppDemo PRIVATE include) # 链接CUDA运行时库(可选,CMake通常自动处理) target_link_libraries(CudaCppDemo PRIVATE CUDA::cudart)
六、常见坑的排查
- 找不到CUDA编译器:确保你装了CUDA Toolkit,并且CMake能定位到它,如果不行,手动指定编译器路径:
set(CMAKE_CUDA_COMPILER "/usr/local/cuda/bin/nvcc") # Linux下的路径,Windows自己调整
- 链接时提示设备函数未定义:检查有没有加
-rdc=true,以及所有用到设备函数的.cu文件都被正确添加到目标里了 - 标准兼容问题:CUDA版本和C版本要匹配,比如CUDA 11支持C17,CUDA 10只支持到C++14,别瞎选高标准
内容的提问来源于stack exchange,提问作者Toothless




