【问题标题】:CMake does not properly find CUDA libraryCMake 无法正确找到 CUDA 库
【发布时间】:2015-01-17 01:25:42
【问题描述】:

我正在尝试构建一个需要 CUDA 的程序。对于我提供的 CMake 脚本:

cmake -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda ..

找到CUDA,CMake运行正常:

staudt ~/workspace/clutbb/cluster/build $ cmake -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda ..                                                                                  
-- Found CUDA: /usr/local/cuda (found version "6.5") 
-- Found Intel TBB
-- Boost version: 1.56.0
-- Found the following Boost libraries:
--   iostreams
--   program_options
-- Looking for include file pthread.h
-- Looking for include file pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE  
-- Could NOT find SDL (missing:  SDL_LIBRARY SDL_INCLUDE_DIR) 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/i11/staudt/workspace/clutbb/cluster/build

但随后链接器步骤失败:

staudt ~/workspace/clutbb/cluster/build $ make
[ 69%] Built target cluster
Linking CXX executable clu
CMakeFiles/clu.dir/clu.cpp.o: In function `initCUDA(int&, CUctx_st*&, int const&)':
clu.cpp:(.text+0x517): undefined reference to `cuInit'
clu.cpp:(.text+0x52b): undefined reference to `cuDeviceGet'
clu.cpp:(.text+0x53f): undefined reference to `cuCtxCreate_v2'
clu.cpp:(.text+0x559): undefined reference to `cuDeviceGetName'
clu.cpp:(.text+0x55e): undefined reference to `cuCtxSynchronize'
CMakeFiles/clu.dir/clu.cpp.o: In function `exitCUDA(int&, CUctx_st*&)':
clu.cpp:(.text+0x684): undefined reference to `cuCtxDestroy_v2'
CMakeFiles/clu.dir/clu.cpp.o: In function `main':
clu.cpp:(.text.startup+0x1092): undefined reference to `cuCtxDestroy_v2'
clu.cpp:(.text.startup+0x10d1): undefined reference to `cuCtxSynchronize'
clu.cpp:(.text.startup+0x10e1): undefined reference to `cuCtxSynchronize'
collect2: error: ld returned 1 exit status
make[2]: *** [bin/clu] Fehler 1
make[1]: *** [bin/CMakeFiles/clu.dir/all] Fehler 2
make: *** [all] Fehler 2

所需的库位于/usr/local/cuda/lib64/stubs/libcuda.so,但我如何将其指出给 cmake 或 make?

【问题讨论】:

  • 应该链接的libcuda.so 通常不是您显示的目录中的那个。正确的libcuda.so驱动程序 安装,而不是CUDA 安装程序。它通常可以在/usr/lib64 或类似的地方找到。在某个地方,您的制作过程中缺少-lcuda,或者库目录搜索路径未设置为指向您机器上libcuda.so 的正确位置。 /usr/local/cuda/... 通常不是寻找 libcuda.so 的正确位置
  • 链接器命令是/usr/bin/c++ -O3 -Wall -ffast-math -DNDEBUG -DLEAN CMakeFiles/clu.dir/clu.cpp.o -o clu -rdynamic /usr/local/cuda/lib64/libcudart.so -ltbb -lboost_iostreams-mt -lboost_program_options-mt -lrt ../src/libcluster.a /usr/local/cuda/lib64/libcudart.so -Wl,-rpath,/usr/local/cuda/lib64 没有-lcuda,我也不知道怎么加。
  • 我稍微更新了我的回复,看看是否能解决您的问题。
  • 我对讨论有点困惑:显然 CMake 报告它找到了 CUDA 但未能生成-lcudalinker 标志,对吧?
  • 简而言之,CUDA 应用分为 2 类。驱动程序 API 应用程序和使用运行时 API 的应用程序。可以说更常见的运行时 API 应用程序不需要链接到 libcuda。所以 CMake “发现” CUDA 大概意味着它被设置为构建一个运行时 API CUDA 应用程序。您将需要了解如何在 CMake 中按下魔法按钮来构建驱动程序 API 应用程序。我不是 CMake 专家。如果您在 CUDA 标签中阅读了您之前的问题,它将讨论驱动程序 API 与运行时 API。 Anycorn 的答案,主要是关于路径,不会解决缺少-lcuda 的问题,我不认为。

标签: c++ cuda makefile cmake


【解决方案1】:

在您现在发布的存档中,有多个项目层次结构。您在问题中发布的实际错误是在 clutbb/cluster/bin 目录中基于 clu.cpp 的 clu 项目的编译和链接过程中发生的。

在同一目录下,有一个 CMakeLists.txt 文件。此文件管理项目层次结构的这一特定级别。

在这个特定的 CMakeLists.txt 文件中,有以下部分:

cuda_add_executable(clu clu.cpp)
target_link_libraries(clu ${CUDA_LIBRARY} ${TBB_LIBRARY} ${Boost_LIBRARIES} rt)
target_link_libraries(clu cluster)

尝试将上面的中间行修改为:

target_link_libraries(clu ${CUDA_LIBRARY} ${TBB_LIBRARY} ${Boost_LIBRARIES} rt cuda)

这应该可以修复链接器命令行中缺少的-lcuda。可能仍然需要在您的计算机上为其提供指向 libcuda.so 的路径,但可能没有必要,具体取决于您的计算机环境的设置方式。

【讨论】:

  • 谢谢,这部分解决了问题。另一个问题是我的系统上没有安装正确的 Nvidia CUDA 驱动程序,因此找不到libcuda.so。最后,我能够构建项目。
【解决方案2】:

在 CMake 3.17+ 上执行此操作的正确方法是使用 FindCUDAToolkit 模块,如下所示:

find_package(CUDAToolkit REQUIRED)
target_link_libraries(my_target PRIVATE CUDA::cudart CUDA::cuda_driver)

CUDA::cuda_driver 目标等同于 -lcuda,当链接器可以找到它时,它是指向正确库的绝对路径。您应该避免通过target_link_libraries 添加系统库以确保可移植性。


如果您有旧版本(CMake 3.0+),您可以使用(现已弃用)FindCUDA 模块来模仿 3.17 模块,如下所示:

find_package(CUDA REQUIRED)

# Do what the new package does
find_library(CUDA_DRIVER_LIBRARY
             NAMES cuda_driver cuda
             HINTS ${CUDA_TOOLKIT_ROOT_DIR}
                   ENV CUDA_PATH
             PATH_SUFFIXES nvidia/current lib64 lib/x64 lib)
if (NOT CUDA_DRIVER_LIBRARY)
    # Don't try any stub directories until we have exhausted all other search locations.
    find_library(CUDA_DRIVER_LIBRARY
                 NAMES cuda_driver cuda
                 HINTS ${CUDA_TOOLKIT_ROOT_DIR}
                       ENV CUDA_PATH
                 PATH_SUFFIXES lib64/stubs lib/x64/stubs lib/stubs stubs)
endif ()
mark_as_advanced(CUDA_DRIVER_LIBRARY)
##

target_include_directories(my_target PRIVATE ${CUDA_INCLUDE_DIRS})
target_link_libraries(my_target PRIVATE ${CUDA_LIBRARIES} ${CUDA_DRIVER_LIBRARY})

This is adapted from the official sources, here.

【讨论】:

    【解决方案3】:

    带有主机调用的 C++ 文件不知道它需要链接到 libcudart。您必须为该文件所在的文件/二进制文件显式设置依赖关系,例如。

    target_link_libraries(clu ${CUDA_LIBRARIES})
    

    以上回复略有错误。无论出于何种原因,似乎 libcuda.so 都安装在了意外的位置。您可以尝试将CMAKE_LIBRARY_PATH 或/和CUDA_LIB_PATH 设置为该路径。

    我认为 CUDA_LIB_PATH 需要在 cmake 之外设置,例如export CUDA_LIB_PATH=/usr/local/cuda/lib64/stubs/

    【讨论】:

    • libcudart 不是这里缺少的库。正如 OP 所指出的,该应用程序似乎正在使用驱动程序 API,并且需要链接到 libcuda。某处缺少-lcuda,或者库搜索不太正确。 CMake 不会很方便地向您显示它发出的命令。
    • @RobertCrovella 啊,是的,我现在明白了。
    • 在 FindCUDA.cmake(至少在 2.8 中)CUDA_LIB_PATH env var 将被搜索 libcuda。如果 cuda 库安装在非标准位置(与帖子一样),这应该有助于至少链接到 libcuda
    猜你喜欢
    • 2017-06-02
    • 1970-01-01
    • 2014-08-02
    • 2014-08-02
    • 1970-01-01
    • 2014-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多