CMake 中使用 CUDA
Combining CUDA and Modern CMake
假设有三个源码文件:
- foo.h 和 foo.cu 是 kernal 函数实现,需要编译成库
- t.cpp 是 main 函数实现,调用 foo 里面的核函数
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CUDA_ARCHITECTURES "75")
set(CMAKE_CUDA_COMPILER "/usr/local/cuda/bin/nvcc")
project(CudaTest LANGUAGES CXX CUDA)
add_library(foo STATIC foo.cu)
target_compile_options(foo PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:--generate-line-info>)
target_compile_features(foo PRIVATE cuda_std_14)
add_executable(t t.cpp)
target_link_libraries(t foo)
target_compile_features(t PRIVATE cxx_std_17)
说明
CUDA 和 CXX 标准也可以用全局生效的方式设置:
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CUDA_STANDARD 14)
set(CMAKE_CUDA_STANDARD_REQUIRED True)
CMAKE_CUDA_ARCHITECTURES
变量如果不设置,可能会报 “Failed to detect a default CUDA architecture” 的错误;CMAKE_CUDA_COMPILER
变量如果不设置,可能会报 “No CMAKE_CUDA_COMPILER could be found” 的错误。不过这两个变量与具体编译环境相关,所以不建议直接在比较规范的 CMakeLists.txt 里面硬编码。
--generate-line-info
这个编译选项是为了让 cuda 编译器生成源码信息,这样 Nsight Compute 才能找到并显示 C++ 源码,否则只能显示汇编代码
Profiler
CUDA 自带两个 profiler 工具,可以很方便地分析程序性能问题,做出针对性地优化:
- Nsight Systems: 分析 CPU/GPU 各个事件在时间线上的占用情况,用于分析优化程序整体的运行流程,其 CLI 和 GUI 程序分别是 nsys 和 nsys-ui
- Nsight Compute: 分析 kernal 函数内部执行细节,还能自动给出一些优化建议,其 CLI 和 GUI 程序分别是 ncu 和 ncu-ui
我在用 ncu 的时候遇到过报错:ERR_NVGPUCTRPERM: Permission issue with Performance Counters
,虽然报错后面给了如何处理的文档链接,但我根据这个文档并没有解决问题,里面少了一点关键步骤。参考这里和这里,永久解决该问题的步骤是:
- 执行
(echo 'options nvidia "NVreg_RestrictProfilingToAdminUsers=0"') | sudo tee -a /etc/modprobe.d/RestrictedProfiling.conf >/dev/null
- 执行
sudo update-initramfs -u
- 重启电脑
- 执行
cat /proc/driver/nvidia/params | grep RmProfilingAdminOnly
,返回RmProfilingAdminOnly: 0
则表示问题已解决
具体 profiler 怎么用,可以参考 GPU Series: Hands-On Session with NSight Systems and Compute