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

相关推荐
张晓~18339948121几秒前
短视频矩阵源码-视频剪辑+AI智能体开发接入技术分享
c语言·c++·人工智能·矩阵·c#·php·音视频
dpxiaolong10 分钟前
RK3588 Android12默认移除导航栏
开发语言·python
Pocker_Spades_A40 分钟前
Python快速入门专业版(二十九):函数返回值:多返回值、None与函数嵌套调用
服务器·开发语言·python
良木林43 分钟前
浅谈原型。
开发语言·javascript·原型模式
烈风1 小时前
004 Rust控制台打印输出
开发语言·后端·rust
一枝小雨1 小时前
【C++】list 容器操作
开发语言·c++·笔记·list·学习笔记
HMBBLOVEPDX1 小时前
C++(继承和多态)
开发语言·c++·继承和多态
yvya_2 小时前
JVM介绍
java·开发语言·jvm
rockmelodies2 小时前
【PHP7内核剖析】-1.1 PHP概述
开发语言·php