【问题标题】:CMake + CUDA "invalid device function" even with correct SM version即使 SM 版本正确,CMake + CUDA “设备功能无效”
【发布时间】:2020-01-14 19:49:01
【问题描述】:

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

我理解它的工作原理是:

  • SASS 代码只能由具有完全相同 SM 版本的 GPU 解释2
  • 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 与静态库和共享库一起使用,我需要编译位置无关代码并启用可分离编译

我现在做的是:

  • 确认我的 Titan Xp 有 SM 6.1 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 版本从 here 编译到同一个二进制文件中,结果仍然相同。

看来,根据to this example,嵌入 PTX 不仅仅是使用 CMake 进行编译,所以现在我会对 SASS 版本感到满意..

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

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

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

【问题讨论】:

  • 根据记忆,Titan Xp 是sm_60
  • 不是根据developer.nvidia.com/cuda-gpus...我也试过60,但都是一样的。
  • 好的,很抱歉提供了误导性信息。

标签: c++ cmake cuda


【解决方案1】:

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

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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-09
    • 1970-01-01
    • 2018-03-31
    • 2014-08-19
    • 1970-01-01
    • 2015-08-08
    • 2015-01-17
    相关资源
    最近更新 更多