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来运行和调试代码啦!

相关推荐
娅娅梨21 分钟前
C++ 错题本--not found for architecture x86_64 问题
开发语言·c++
兵哥工控25 分钟前
MFC工控项目实例二十九主对话框调用子对话框设定参数值
c++·mfc
汤米粥27 分钟前
小皮PHP连接数据库提示could not find driver
开发语言·php
冰淇淋烤布蕾30 分钟前
EasyExcel使用
java·开发语言·excel
我爱工作&工作love我33 分钟前
1435:【例题3】曲线 一本通 代替三分
c++·算法
拾荒的小海螺36 分钟前
JAVA:探索 EasyExcel 的技术指南
java·开发语言
马剑威(威哥爱编程)1 小时前
哇喔!20种单例模式的实现与变异总结
java·开发语言·单例模式
娃娃丢没有坏心思1 小时前
C++20 概念与约束(2)—— 初识概念与约束
c语言·c++·现代c++
lexusv8ls600h1 小时前
探索 C++20:C++ 的新纪元
c++·c++20
lexusv8ls600h1 小时前
C++20 中最优雅的那个小特性 - Ranges
c++·c++20