CUDA和C++混合编程及CMakeLists.txt

1. 概要

首先认识一个问题,单从CMakeLists.txt的角度来看,无法同时使用两种编译器编译两种语言。不过直接编写Makefile是可以的,通过设置不同的任务,可以实现一个Makefile编译两个语言。但这不是这里要讨论的重点。

使用CUDA和C++进行混合编程的意思是:在cpp文件中调用CUDA函数,实现加速。

所以混合编程有两种方法:

1.1 直接编译

1.2 将CUDA工程编译成库,然后在我们的cpp工程中使用target_link_libraries()来链接到我们刚编译好的CUDA库。

2. 注意点

我们要做的事情是将CUDA工程编译成库,然后在我们的cpp工程中使用target_link_libraries()来链接到我们刚编译好的CUDA库。

有几个需要注意的地方,下面这些都是在cpp的CMakeLists.txt中:

  1. The project() command will initialize many CMake variables concerning your system and compiler. As such, it sets the languages that your CMake project will be using. Without specifying any language in the project() command, the defaults (C and CXX) are enabled:

    bash 复制代码
    # Initialize for C and C++ languages.
    project(cmake_and_cuda)

    啥意思?意思是说,CMakeLists.txt中的 project() 作用是根据你的系统和编译器初始化CMake变量,所以,projects()的作用是设置你CMake项目的语言,如果没有特别指出,默认使用C和CXX

  2. project() 应该紧跟在cmake_minimum_required()后面,这里因为我们需要引用cuda库,所以需要设置语言的时候加上cuda,有两种方式:

    bash 复制代码
    project(cmake_and_cuda CUDA CXX)
    # 或者如下:
    project(cmake_and_cuda CUDA CXX)
    enable_language(CUDA)
  3. 设置CUDA架构

    后面的数值需要根据显卡来确定,查阅 https://developer.nvidia.com/cuda-gpus,比如我的是8.6这里就设置86

    cpp 复制代码
    set(CMAKE_CUDA_ARCHITECTURES 86)
  4. 给cuda库进行编译,并且链接到cpp程序中去【直接编译的方法跳过】

    bash 复制代码
    add_subdirectory(kernels)
    target_link_libraries(main kernels)

3. 实现

main.cpp

cpp 复制代码
#include "kernels/test.cuh"

int main() {
  wrap_test_print();

  return 0;
}

版本一:

直接编译:

bash 复制代码
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)

project(cmake_and_cuda)
set(CMAKE_CUDA_ARCHITECTURES 86)
enable_language(CUDA)
# 把cu当成普通cpp来用
add_executable(main main.cpp kernels/test.cu)

版本二:

编译CUDA成库再链接方式的CMakeLists.txt

bash 复制代码
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)

project(cmake_and_cuda)

set(CMAKE_CUDA_ARCHITECTURES 86)
#set(CMAKE_CUDA_COMPILER /usr/local/cuda-11.1/bin/nvcc)
#set(CUDACXX /usr/local/cuda-11.1/bin/nvcc)

enable_language(CUDA)

add_executable(main main.cpp)
add_subdirectory(kernels)

# set_property(TARGET main 
#              PROPERTY CUDA_SEPARABLE_COMPILATION ON)
target_link_libraries(main kernels)

test.cuh:cuda的头文件

cpp 复制代码
#ifndef TEST_CUH__
#define TEST_CUH__

#include <stdio.h>

void wrap_test_print();

#endif

test.cu

cpp 复制代码
#include "test.cuh"
__global__ void test_print(){
  printf("Hello World!\n");
}

void wrap_test_print() {
  test_print<<<1, 1>>>();
  cudaDeviceSynchronize();
  return;
}

cuda的CMakeLists.txt【直接编译的方法不要这个CMakeLists.txt】

bash 复制代码
enable_language(CUDA)
add_library(kernels
test.cu
test.cuh
)
target_compile_features(kernels PUBLIC cxx_std_11)
set_target_properties(kernels
                       PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
target_link_libraries(kernels)

最终目录结构:

bash 复制代码
├── CMakeLists.txt
├── kernels
│   ├── CMakeLists.txt
│   ├── test.cu
│   └── test.cuh
└── main.cpp

编译运行,输出Hello World!

4. CLion注意点

如果你用的是clion来编写cpp和cuda的混合,很有可能你直接使用界面上的运行按钮会报错,找不到文件blabla...,比如fatal error: cuda_runtime.h: 没有那个文件或目录,但是其实你从终端里面cmake make是能通过也是正常执行的,只要你在终端编过一次,IDE中即使一堆报错波浪线也可以run,很莫名其妙。

解决办法,在CMakeLists中加上一句include_directories(/usr/local/cuda-11.1/targets/x86_64-linux/include),这里的路径可以通过在命令行执行locate cuda_runtime.h来获得,这样所有clion中所有和cuda相关的报红色波浪线的地方都可以加上#include <cuda_runtime.h>,这样就可以愉快的CLion来运行和调试代码啦!

相关推荐
多恩Stone2 分钟前
【RoPE】Flux 中的 Image Tokenization
开发语言·人工智能·python
李日灐4 分钟前
C++进阶必备:红黑树从 0 到 1: 手撕底层,带你搞懂平衡二叉树的平衡逻辑与黑高检验
开发语言·数据结构·c++·后端·面试·红黑树·自平衡二叉搜索树
汉克老师10 分钟前
GESP2025年6月认证C++二级( 第一部分选择题(1-8))
c++·循环结构·表达式·分支结构·gesp二级·gesp2级
Risehuxyc12 分钟前
备份三个PHP程序
android·开发语言·php
rainbow688915 分钟前
C++高性能框架Drogon:后端开发新标杆
c++
Q741_14716 分钟前
C++ 优先级队列 大小堆 模拟 力扣 703. 数据流中的第 K 大元素 每日一题
c++·算法·leetcode·优先级队列·
lly20240618 分钟前
PHP Error: 常见错误及其解决方法
开发语言
网安墨雨19 分钟前
Python自动化一------pytes与allure结合生成测试报告
开发语言·自动化测试·软件测试·python·职场和发展·自动化
毕设源码李师姐21 分钟前
计算机毕设 java 基于 java 的图书馆借阅系统 智能图书馆借阅综合管理平台 基于 Java 的图书借阅与信息管理系统
java·开发语言·课程设计
忆~遂愿21 分钟前
Runtime 上下文管理:计算实例的生命周期、延迟最小化与上下文切换优化
java·大数据·开发语言·人工智能·docker