CMake + CUDA "invalid device function"即使使用正确的 SM 版本

CMake + CUDA "invalid device function" even with correct SM version

本文关键字:版本 SM CUDA invalid device function CMake      更新时间:2023-10-16

我在内核启动时不断收到"无效的设备功能"。 谷歌为此提供了大量的实例,但是所有这些实例似乎都与二进制文件中嵌入的嵌入式SASS/PTX代码不匹配有关。

我理解它是如何工作的方法是:

  • SASS 代码只能由具有完全相同的 SM 版本 2 的 GPU 解释
  • PTX 代码是向前兼容的,即任何较新的 GPU 都将能够运行代码(但是,驱动程序需要 JIT( 2
  • 我需要通过将合适的 -arch 命令传递给nvcc来指定我想要的目标:-gencode arch=compute_30,code=sm_30将创建一个针对 SM 3.0 的 SASS,-gencode arch=compute_60,code=compute_60将创建 PTX 代码 1
  • 要将 cuda 与静态和共享库一起使用,我需要针对与位置无关的代码进行编译并启用可分离的编译

我现在做的是:

  • 确认我的泰坦 Xp 6.1 有 SM 5
  • 强制 nvcc 生成兼容代码 3

    set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode arch=compute_61,code=sm_61 -gencode arch=compute_61,code=compute_61 -gencode arch=compute_30,code=sm_30 -gencode arch=compute_30,code=compute_30")
    
  • 确认这被编译到我的目标文件中,cuobjdump

    ./cuobjdump /mnt/linuxdata/campvis-nx/build/bin/libcuda-interop-cuda.a 
    member /mnt/linuxdata/campvis-nx/build/bin/libcuda-interop-cuda.a:test.cu.o:
    Fatbin ptx code:
    ================
    arch = sm_61
    code version = [6,4]
    producer = <unknown>
    host = linux
    compile_size = 64bit
    compressed
    ptxasOptions = --compile-only  
    Fatbin elf code:
    ================
    arch = sm_61
    code version = [1,7]
    producer = <unknown>
    host = linux
    compile_size = 64bit
    compressed
    Fatbin ptx code:
    ================
    arch = sm_30
    code version = [6,4]
    producer = <unknown>
    host = linux
    compile_size = 64bit
    compressed
    ptxasOptions = --compile-only  
    Fatbin elf code:
    ================
    arch = sm_30
    code version = [1,7]
    producer = <unknown>
    host = linux
    compile_size = 64bit
    compressed
    member /mnt/linuxdata/campvis-nx/build/bin/libcuda-interop-cuda.a:mocs_compilation.cpp.o:
    
  • 意识到只有一部分(SASS 部分?(链接到我的共享库(为什么??

    ./cuobjdump /mnt/linuxdata/campvis-nx/build/bin/libcampvis-modules.so 
    Fatbin elf code:
    ================
    arch = sm_61
    code version = [1,7]
    producer = <unknown>
    host = linux
    compile_size = 64bit
    Fatbin elf code:
    ================
    arch = sm_30
    code version = [1,7]
    producer = <unknown>
    host = linux
    compile_size = 64bit
    

我什至尝试将这里的所有 SM 版本编译到相同的二进制文件中,结果仍然相同。

似乎根据这个例子,嵌入 PTX 比仅仅使用 CMake 编译它要做更多的工作,所以现在我会对 SASS 版本感到满意。

我是否误解了上述任何信息?

"设备功能无效"错误还有其他可能的原因吗?

如果有帮助,我可以发布代码,但我觉得这更像是一个构建系统问题。

最终,正如预期的那样,这是由于构建系统设置问题。

TLDR 版本:
我设法通过使用我的 CUDA 代码将库从STATIC更改为SHARED来修复它。

为了修复它,我首先使用了来自 FindCuda CMake 的自动架构检测(它似乎已经创建了 SM 6.1,所以我在那里很担心(

cuda_select_nvcc_arch_flags(ARCH_FLAGS Auto)
list(APPEND CUDA_NVCC_FLAGS ${ARCH_FLAGS})

我正在将其集成到其中的应用程序是使用共享库进行模块化的。我无法直接在新模块中包含 .cu 文件,因为 nvcc 不喜欢某些编译标志。因此,我的目的是创建一个单独的静态库,其中只有 cuda 代码将链接到共享模块。但是,这似乎没有正确地将设备代码包含在共享库中(可能是因为它们与"普通"c ++ 链接器链接?

最终,这是我最终使用的代码:

add_library(cuda-interop SHARED [c++ only code])
file(GLOB cuda_SOURCES "modules/cudainterop/cuda/*.cu")
# the library that only has the cuda code
add_library(cuda-interop-cuda SHARED ${cuda_SOURCES})
set_target_properties(cuda-interop-cuda PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
set_target_properties(cuda-interop-cuda PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_link_libraries(cuda-interop PRIVATE cuda-interop-cuda)