【问题标题】:CUDA + CMake target library dependence breaks on different machineCUDA + CMake 目标库依赖在不同机器上中断
【发布时间】:2017-05-15 22:48:32
【问题描述】:

我最近尝试在同一台机器上切换到另一个 Linux 发行版后构建我的 https://github.com/eyalroz/cuda-api-wrappers/ 库的示例。奇怪的是,我遇到了链接问题。命令:

/usr/bin/c++   -Wall -std=c++11 -g  CMakeFiles/device_management.dir/examples/by_runtime_api_module/device_management.cpp.o -o examples/bin/device_management -rdynamic lib/libcuda-api-wrappers.a -Wl,-Bstatic -lcudart_static -Wl,-Bdynamic -lpthread -ldl -lrt

找不到 CUDA 运行时库,我得到:

CMakeFiles/device_management.dir/examples/by_runtime_api_module/device_management.cpp.o: In function `cuda::device::peer_to_peer::get_attribute(cudaDeviceP2PAttr, int, int)':
/home/eyalroz/src/mine/cuda-api-wrappers/src/cuda/api/device.hpp:38: undefined reference to `cudaDeviceGetP2PAttribute'
collect2: error: ld returned 1 exit status

但是如果我添加-L/usr/local/cuda/lib64 它构建得很好。这以前没有发生过;它不会发生在我检查过的另一台机器上,甚至不会发生在同一 CMakeLists.txt 中使用 CUDA 运行时的其他目标上(如 version_managament)。

FindCUDA 似乎可以找到所有内容,因为 ${CUDA_LIBRARIES} 的值是 /usr/local/cuda/lib64/libcudart_static.a;-lpthread;dl;/usr/lib/x86_64-linux-gnu/librt.so。而CMakeLists.txt中的目标行是:

add_executable(device_management EXCLUDE_FROM_ALL examples/by_runtime_api_module/device_management.cpp)
target_link_libraries(device_management cuda-api-wrappers ${CUDA_LIBRARIES})

正如其他相关问题的答案中所建议的那样(例如here)。为什么会这样?我应该“手动”添加-L 开关吗?

编辑:遵循@RobertCrovella 的建议,这里是 ld 搜索路径:

$ gcc -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,;  ,g' | tr \; \\012 | tr ':' "\n" | tail -n +3
  /usr/local/cuda/lib64/x86_64-linux-gnu/5/
/usr/local/cuda/lib64/x86_64-linux-gnu/
/usr/local/cuda/lib/
/usr/lib/gcc/x86_64-linux-gnu/5/
/usr/x86_64-linux-gnu/lib/x86_64-linux-gnu/5/
/usr/x86_64-linux-gnu/lib/x86_64-linux-gnu/
/usr/x86_64-linux-gnu/lib/
/usr/lib/x86_64-linux-gnu/5/
/usr/lib/x86_64-linux-gnu/
/usr/lib/
/lib/x86_64-linux-gnu/5/
/lib/x86_64-linux-gnu/
/lib/
/usr/lib/x86_64-linux-gnu/5/
/usr/lib/x86_64-linux-gnu/
/usr/lib/
/usr/local/cuda/lib64/
/usr/x86_64-linux-gnu/lib/
/usr/lib/
/lib/
/usr/lib/

$ ld --verbose | grep SEARCH_DIR | tr -s ' ;' \\012
SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu")
SEARCH_DIR("=/lib/x86_64-linux-gnu")
SEARCH_DIR("=/usr/lib/x86_64-linux-gnu")
SEARCH_DIR("=/usr/local/lib64")
SEARCH_DIR("=/lib64")
SEARCH_DIR("=/usr/lib64")
SEARCH_DIR("=/usr/local/lib")
SEARCH_DIR("=/lib")
SEARCH_DIR("=/usr/lib")
SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64")
SEARCH_DIR("=/usr/x86_64-linux-gnu/lib")

注意事项:

  • 是的,我知道CMakeLists.txt 那里很丑。

【问题讨论】:

  • 可能(不太可能?)两台机器上的ld 链接器搜索路径配置不同。 IMO,将ld 链接器搜索路径(不是动态库加载路径)设置为自动搜索/usr/local/cuda/lib64 将是不寻常,所以我认为最好的建议是明确识别-L /desired/path/to/cuda/libs .您可以使用here 建议的方法之一(例如在第三个答案中)来比较两台机器之间的ld 链接器搜索路径(不是动态库加载路径),以证明或反驳这个理论。
  • 假设您显示的第一个 c++ 命令行是在通过和失败的机器之间相同发出的,那么这不是/不应该是 CMake 问题,我不不认为。至少任何 CMake 配置都无法解释这种行为差异。因此,对行为差异的调查可能会遵循我之前评论中指出的路径。
  • 抛开库是问题恰好是 CUDA 运行时 API 库这一事实不谈,究竟是什么让这个问题成为关于 CUDA 的问题?不就是“cmake 和 g++ 在一个系统上找不到库,而是在另一个概念上相同的系统上找到库。为什么?”
  • @RobertCrovella:不幸的是,我无法在我替换的操作系统上发出命令 :-( 另外,请参阅编辑 - ld 搜索路径不包含 CUDA 库目录,但 gcc 确实包含它看看我想的环境。
  • 如果您希望CMake 发出非常适合各种CUDA 安装的命令,那么我的建议是强制CMake 发出正在执行链接的c++ 命令以一种明智的方式——即明确地包含我已经提到的-L 开关。如果这是您的意图,那么这恰好在另一台机器上按原样工作的事实是一个红鲱鱼,IMO,您应该提出问题来询问“我怎样才能让 CMake 添加必要的 -L 切换到在这种情况下这个命令行?”

标签: cuda linker cmake


【解决方案1】:

TL;DR:

在 FindCUDA 调用之后,添加以下行:

get_filename_component(CUDA_LIBRARY_DIR ${CUDA_CUDART_LIBRARY} DIRECTORY)
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-L${CUDA_LIBRARY_DIR}")

并且构建应该在两个系统上都成功。

讨论:

(在 cmets 中解释 @RobertCrovella 和我自己:)

OP 期望,如果以下成立:

  • FindCUDA 成功
  • ${CUDA_LIBRARIES} 包含静态或动态 CUDA 运行时库的有效完整路径
  • 使用target_link_libraries(relevant_target ${CUDA_LIBRARIES}) 表示库依赖关系

...那么他尝试的基于 CMake 的构建应该可以在各种有效的 CUDA 安装上成功。 (很遗憾)不是这样,因为虽然 FindCUDA 确实找到了 CUDA 库路径,但它实际上并没有让您的链接器搜索该路径。所以失败实际上应该是预期的。由于“侥幸”,或者更确切地说,由于 OP 已将 CUDA 库目录添加到链接器的搜索路径,不知何故,该构建已在 OP 的旧系统上运行。

必须使用-L/path/to/cuda/libraries 开关发出链接命令,以便链接器知道在哪里查找(未指定路径)库称为与CUDA 相关的-l 开关(在OP 的情况下,@987654329 @)。

This answer 讨论了如何在 CMake 中针对不同类型的目标执行此操作。如果您不熟悉 -l-L 选项,您可能还想查看 man gcc(GCC 手册页,也可使用 here)。

【讨论】:

  • @talonmies 完成,抱歉。是你今天对我的一堆问题投了反对票吗?
  • 绝对不是。由于您的编辑,我只在它出现在活动问题列表中时才注意到它。如果您被某人连续投票,系统可能会检测到它并在接下来的 24 小时内将其撤消。
  • @talonmies:好的,抱歉。只是对大约 0 票的问题投了 3 票,其中至少有两个是我自己的答案,然后我在这里看到了你的评论。
猜你喜欢
  • 2016-09-04
  • 1970-01-01
  • 1970-01-01
  • 2014-10-07
  • 1970-01-01
  • 1970-01-01
  • 2011-12-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多