问题描述
我有一个基于CUDA的静态库(.cu和.cpp文件的混合物),我试图将其链接到测试文件test.cu
,该文件将包含库中的lib_file_1.cuh
。因此,我想将我的.cu可执行文件链接到我的CUDA库,直到现在,在链接器步骤中使用g ++代替nvcc。 如何解决此问题?,因为由于错误的链接,我现在只收到undefined reference to "__cudaRegisterLinkedBinary_name_..."
类型的错误。
根目录,根目录/ my_library和根目录/测试代码中的以下CMakeLists.txt文件应该可以重现该问题。
根:
cmake_minimum_required(VERSION 3.17.3)
project(library_test LANGUAGES CUDA CXX)
if (MSVC)
add_compile_options(/W4)
else()
add_compile_options(-Wall -Wextra -fno-omit-frame-pointer -g)
endif()
add_subdirectory(my_library)
add_subdirectory(test)
set(CMAKE_VERBOSE_MAKEFILE ON)
target_link_libraries(tester PRIVATE my_library)
在root / my_library中:
find_package(CUDA COMPONENTS THRUST REQUIRED)
add_library(my_library STATIC src/lib_file_1.cu)
target_include_directories(my_library PUBLIC
include
${CUDA_INCLUDE_DIRS}
)
target_compile_options(my_library
PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler -Wno-pedantic -dc -gencode arch=compute_61,code=sm_61 --expt-relaxed-constexpr -Xlinker -dlink>
)
target_link_libraries(my_library
PUBLIC ${CUDA_LIBRARIES}
)
在根目录/测试中:
add_executable(tester test.cu)
target_include_directories(tester PUBLIC
${CMAKE_SOURCE_DIR}/my_library
)
让实例lib_file_1.cuh
为:
#include <thrust/device_vector.h>
__host__ __device__ void foo(double &r);
lib_file_1.cu
:
#include <thrust/device_vector.h>
#include "lib_file_1.cuh"
__host__ __device__ void foo(double &r)
{
r = 0;
}
和test.cu
:
#include "lib_file_1.cuh"
int main()
{
double random_number;
foo(random_number);
return 0;
}
我已经看到,该错误是一个潜在的问题,如6.6.3隐式CUDA主机代码https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#potential-separate-compilation-issues所述,我发现了几篇文章解决了一般命令行项目构建/手动makefile构建的问题。 但是,我还没有找到解决cmake的好方法。
在根目录/调试中运行make VERBOSE=1
后使用cmake -DCMAKE_BUILD_TYPE=debug ..
链接CUDA可执行测试器时,将得到以下结果:
/usr/bin/g++ CMakeFiles/tester.dir/test.cu.o -o tester ../my_library/libmy_library.a /usr/local/cuda-10.2/lib64/libcudart_static.a -lpthread -ldl /usr/lib/x86_64-linux-gnu/librt.so -lcudadevrt -lcudart_static -L"/usr/local/cuda-10.2/targets/x86_64-linux/lib/stubs" -L"/usr/local/cuda-10.2/targets/x86_64-linux/lib" -lrt -lpthread -ldl
CMakeFiles/tester.dir/test.cu.o: In function `__sti____cudaRegisterAll()':
/tmp/tmpxft_00005a8a_00000000-5_test.cudafe1.stub.c:20: undefined reference to `__cudaRegisterLinkedBinary_39_tmpxft_00005a8a_00000000_6_test_cpp1_ii_main'
../my_library/libmy_library.a(lib_file_1.cu.o): In function `__sti____cudaRegisterAll()':
/tmp/tmpxft_000057c7_00000000-5_lib_file_1.cudafe1.stub.c:20: undefined reference to `__cudaRegisterLinkedBinary_45_tmpxft_000057c7_00000000_6_lib_file_1_cpp1_ii__Z3fooRd'
collect2: error: ld returned 1 exit status
test/CMakeFiles/tester.dir/build.make:106: recipe for target 'test/tester' failed
解决方法
显然,添加
set_target_properties(my_library PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
到root/my_library
中的CMakeLists.txt可以解决问题。我确实在全球尝试了该选项
set(CUDA_SEPARABLE_COMPILATION ON)
root
目录中CMakeLists.txt中的,但这无效。我不知道为什么。