为 OptiX 获取 CUDA 上下文时未定义对 `cuCtxGetCurrent` 的引用

undefined reference to `cuCtxGetCurrent` while getting CUDA context for OptiX

我正在尝试学习如何将 OptiX 实施到我的 C++ 项目中。第一步是使用 cuCtxGetCurrent(&some_CUcontext_variable) 获取当前 CUDA 上下文,但是我收到一个编译时错误,指出我对 cuCtxGetCurrent.

进行了未定义的引用

这是我的:

我认为这个错误与 linker 相关,所以我假设我的 CMakeLists 中遗漏了一些东西,但我不知道是什么。请告诉我如何解决这个问题!

在此先感谢您的帮助!


更新 #2:已解决

像这样的时刻让我惊慌失措:我所要做的只是将 cuda 直接放入我的目标 link 库中。不是 -lcudaCUDA::cuda,只是 cuda。 link 以某种方式在驱动程序中编辑,现在看起来正在编译。


[旧的,但保留以供参考] 更新 #1:这是我的 CMakeLists.txt

很抱歉我的原始代码中缺少代码 post。我试图避免粘贴大块的任意代码。

cmake_minimum_required(VERSION 3.17)
project(My_Project_Name CUDA CXX)

set(CMAKE_CXX_STANDARD 14)

set(CMAKE_MODULE_PATH
    "${CMAKE_SOURCE_DIR}/cmake"
    ${CMAKE_MODULE_PATH})

find_package(CUDAToolkit REQUIRED)
find_package(OptiX REQUIRED VERSION 7.0)

add_executable(
    ${PROJECT_NAME}
    main.cpp [and other cpp and cu files])

# For project
set_target_properties(
    ${PROJECT_NAME}
    PROPERTIES
    CUDA_SEPARABLE_COMPILATION ON
)
target_compile_options(
    ${PROJECT_NAME}
    PRIVATE
    $<$<COMPILE_LANGUAGE:CUDA>:
    -arch=sm_61
    -gencode arch=compute_52,code=sm_52>
)
target_include_directories(
    ${PROJECT_NAME}
    PRIVATE
    include
    ${OptiX_INCLUDE}
)
target_link_libraries(
    ${PROJECT_NAME}
    PRIVATE
    CUDA::cudart
    CUDA::cublas
)

正如@talonmies 所说,CUDA 有两个(官方)主机端 API:“CUDA 运行时 API”和“CUDA 驱动程序 API”;你可以阅读它们之间的区别 here.

您提到了与运行时相关的文件和 CMake 标识符 API:cuda_runtime.hCUDA::cudart。但是 - “CUDA 上下文”是驱动程序 API 的概念,cuCtxGetCurrent() 等是驱动程序 API 调用。

具体来说,“未定义的引用”确实是一个 linker 错误。在您的情况下,您需要 link 使用 CUDA 驱动程序。作为一个库,在 Linux 系统上,它被称为 libcuda.so。为此,对于名为 ERPT_Render_Engine 的可执行文件,您需要添加命令:

target_link_libraries(ERPT_Render_Engine cuda)

我还要说你上面列出的 CMakeLists.txt 看起来很奇怪,因为它定义了一个不存在的目标的依赖项——项目名称;您的相关目标是您的可执行文件。

另外 - CUDA 上下文并不仅仅因为你创建了你的进程而存在。在使用 cuCtxGetCurrent().

获取当前上下文之前,您需要初始化驱动程序、创建上下文并使其成为当前上下文 - 或者让其他东西为您做这件事(比如库)

最后,如果您有兴趣,我正在研究一个 C++ 包装器库,它涵盖了(大部分)驱动程序和运行时 API 的主机端功能。一些示例代码:

cuda::initialize_driver();
(cuda::device::count() > 0) or die_("No CUDA devices on this system") {}
auto device_id =  cuda::device::default_device_id;
auto device = cuda::device::get(device_id);
auto context = cuda::context::create(device);
//etc. etc.

但同样 - 你真的不必使用它,它只是可选的并且仍在开发中。