我如何通过CMake建立我的自定义CUDA库并正确链接到它?



我正在尝试使用cmake来构建我自己的库。代码由CUDA C/CXX完成。我的CUDA代码和CMake脚本如下:

代码结构:

.
├── include
│   └── Function.cuh
├── lib
│   ├── build
│   └── CMakeLists.txt
├── src
│   └── Function.cu
└── Test
├── bin
├── build
├── CMakeLists.txt
├── compileCode.sh
└── src
└── main.cu
8 directories, 6 files

头文件:

#pragma once
#include <algorithm>
#include <chrono>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cuda.h>
#include <cuda_runtime.h>
#include <curand.h>
#include <curand_kernel.h>
#include <device_launch_parameters.h>
#include <fstream>
#include <iostream>
#include <map>
#include <random>
#include <sstream>
#include <stdlib.h>
#include <sys/time.h>
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <vector>
using namespace std;
__global__ void Function();

源文件:

#include "Function.cuh"
__global__ void Function()
{
int i = threadIdx.x + blockIdx.x * blockDim.x;
if (i > 2)
return;
printf("Function %dn", i);
};

用户界面,即main.cu:

#include "Function.cuh"
int main()
{
Function<<<1, 3>>>();
cudaDeviceSynchronize();
return 0;
};

构建库的CMake文件

cmake_minimum_required (VERSION 3.7)
project (generate_lib)
enable_language(CUDA)
set (SCRIPT_ROOT $ENV{HOME}/Desktop/cuda_custom_lib_test)
include_directories(${SCRIPT_ROOT}/include)
file(GLOB_RECURSE SRC_CU_PATH ${SCRIPT_ROOT}/src/*.cu)
SET (CMAKE_VERBOSE_MAKEFILE TRUE)
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --display_error_number")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --diag_suppress=3057")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --diag_suppress=1301")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --diag_suppress=3059")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -arch=sm_60 -std=c++17 -rdc=true")
add_library (CUDA_CUSTOM_LIB_TEST_shared SHARED ${SRC_CU_PATH})
add_library(CUDA_CUSTOM_LIB_TEST_static STATIC ${SRC_CU_PATH})
set_target_properties(CUDA_CUSTOM_LIB_TEST_shared PROPERTIES OUTPUT_NAME "cuda_custom_lib_test")
set_target_properties(CUDA_CUSTOM_LIB_TEST_static PROPERTIES OUTPUT_NAME "cuda_custom_lib_test")
set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
TARGET_LINK_LIBRARIES( CUDA_CUSTOM_LIB_TEST_shared ${CUDA_LIBRARIES})
TARGET_LINK_LIBRARIES( CUDA_CUSTOM_LIB_TEST_static ${CUDA_LIBRARIES})

将库链接到主库的CMake文件。铜文件

cmake_minimum_required (VERSION 3.5)
project (MAIN_TEST)
enable_language(CUDA)
set (SCRIPT_ROOT $ENV{HOME}/Desktop/cuda_custom_lib_test)
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) ## bin is the EXECUTABLE_OUTPUT_PATH
set (SRC_LIST ${PROJECT_SOURCE_DIR}/src/main.cu)
include_directories(${SCRIPT_ROOT}/include)
find_library(LIBTEST libcuda_custom_lib_test.so HINTS ${SCRIPT_ROOT}/lib)
# find_library(LIBTEST libcuda_custom_lib_test.a HINTS ${SCRIPT_ROOT}/lib)
ADD_EXECUTABLE(main
${SRC_LIST}
)
TARGET_LINK_LIBRARIES( main ${CUDA_LIBRARIES})
TARGET_LINK_LIBRARIES( main ${LIBTEST})
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --display_error_number")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --diag_suppress=3057")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --diag_suppress=1301")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --diag_suppress=3059")
SET (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -arch=sm_60 -std=c++17")

我确实成功地用第一个CMakeLists.txt构建了库。然而,将第二个CMakeLists.txt库链接到main.cu文件后,内核函数不工作,并且没有打印任何内容。

我也试图将libcuda_custom_lib_test.a链接到main.cu文件,我得到了以下错误信息:

/home/~/Desktop/cuda_custom_lib_test/lib/libcuda_custom_lib_test.a(Function.cu.o): In function `__sti____cudaRegisterAll()':
tmpxft_00002db8_00000000-5_Function.cudafe1.cpp:(.text+0xaac): undefined reference to `__cudaRegisterLinkedBinary_43_tmpxft_00002db8_00000000_6_Function_cpp1_ii_83310bf0'
collect2: error: ld returned 1 exit status

我的cmakelist有什么问题?

第一个CMakeLists.txt,可以构建共享和静态库。然后,使用NVCC编译用户界面并链接到静态库。例如,可以转到Test库,然后输入

nvcc ./src/main.cu ../lib/libcuda_custom_lib_test.a -o ./bin/main -I ../include -arch=sm_60 -rdc=true

,然后用

运行代码
./bin/main

,最后在终端

上获取信息
~/Desktop/cuda_custom_lib_test/Test$ ./bin/main
Function 0
Function 1
Function 2

我不确定为什么这个方法能解决问题。但关键是,使用静态库时,不需要使用-l。相反,只需将静态库名称(带路径)放在main.cu后面。

既然NVCC工作得很好,我认为我们可以使用CMake调用NVCC来做同样的事情。但是我失败了。我把CMakeLists.txt放在这里。如果有人能纠正,请评论。

cmake_minimum_required (VERSION 3.8)
project (MAIN_TEST)
find_package(CUDA)
set (SCRIPT_ROOT $ENV{HOME}/Desktop/cuda_custom_lib_test)
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) ## bin is the EXECUTABLE_OUTPUT_PATH
set (SRC_LIST ${PROJECT_SOURCE_DIR}/src/main.cu)
# set (SRC_LIST ${SRC_LIST} ${SCRIPT_ROOT}/lib/libcuda_custom_lib_test.a)
include_directories(${SCRIPT_ROOT}/include)
# find_library(LIBTEST libcuda_custom_lib_test.so HINTS ${SCRIPT_ROOT}/lib)
# find_library(LIBTEST libcuda_custom_lib_test.a HINTS ${SCRIPT_ROOT}/lib)
CUDA_ADD_EXECUTABLE(main
${SRC_LIST} ${SCRIPT_ROOT}/lib/libcuda_custom_lib_test.a
OPTIONS -arch=sm_60 -std=c++17 -rdc=true
)
# target_link_libraries(main ${SCRIPT_ROOT}/lib/libcuda_custom_lib_test.a)
# set(CMAKE_VERBOSE_MAKEFILE ON)

错误信息是

[ 50%] Building NVCC (Device) object CMakeFiles/main.dir/src/main_generated_main.cu.o
Scanning dependencies of target main
[100%] Linking CXX executable ../bin/main
CMakeFiles/main.dir/src/main_generated_main.cu.o: In function `main':
/home/~/Desktop/cuda_custom_lib_test/Test/src/main.cu:5: undefined reference to `Function()'
CMakeFiles/main.dir/src/main_generated_main.cu.o: In function `__sti____cudaRegisterAll()':
/tmp/tmpxft_00004857_00000000-5_main.cudafe1.stub.c:18: undefined reference to `__cudaRegisterLinkedBinary_39_tmpxft_00004857_00000000_6_main_cpp1_ii_main'
collect2: error: ld returned 1 exit status
CMakeFiles/main.dir/build.make:79: recipe for target '../bin/main' failed
make[2]: *** [../bin/main] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/main.dir/all' failed
make[1]: *** [CMakeFiles/main.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

看到CMake坚持将main.cu编译成CXX可执行文件,而我并不打算使用g++,这很奇怪。

最新更新