cuda & rdc & thrust in multiple shared objects results in registerEntry Function 中的 SIGSEGV

标签 cuda cmake thrust .so

我正在尝试在两个共享库中运行可重定位设备代码,它们都使用 cuda-thrust。如果我停止在 kernel.cu 中使用 thrust,一切都运行良好,这不是一个选项。

编辑:如果 rdc 被禁用,该程序也能正常工作。对我来说也不是一个选择。

它编译正常,但在运行时因段错误而停止。 gdb 告诉我这个:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000422cc8 in cudart::globalState::registerEntryFunction(void**, char const*, char*, char const*, int, uint3*, uint3*, dim3*, dim3*, int*) ()
(cuda-gdb) bt
#0  0x0000000000422cc8 in cudart::globalState::registerEntryFunction(void**, char const*, char*, char const*, int, uint3*, uint3*, dim3*, dim3*, int*) ()
#1  0x000000000040876c in __cudaRegisterFunction ()
#2  0x0000000000402b58 in __nv_cudaEntityRegisterCallback(void**) ()
#3  0x00007ffff75051a3 in __cudaRegisterLinkedBinary(__fatBinC_Wrapper_t const*, void (*)(void**), void*) ()
from /home/mindoms/rdctestmcsimple/libkernel.so
#4  0x00007ffff75050b1 in __cudaRegisterLinkedBinary_66_tmpxft_00007a5f_00000000_16_cuda_device_runtime_    compute_52_cpp1_ii_8b1a5d37 () from /home/user/rdctestmcsimple/libkernel.so
#5  0x000000000045285d in __libc_csu_init ()
#6  0x00007ffff65ea50f in __libc_start_main () from /lib64/libc.so.6

这是显示错误的精简示例(使用 cmake)。

主要.cpp:

#include "kernel.cuh"
#include "kernel2.cuh"

int main(){
  Kernel k;
  k.callKernel();

  Kernel2 k2;
  k2.callKernel2();
}

内核.cuh:

#ifndef __KERNEL_CUH__
#define __KERNEL_CUH__
  class Kernel{
  public:
    void callKernel();
  };
#endif

内核.cu:

#include "kernel.cuh"
#include <stdio.h>
#include <iostream>
#include <thrust/device_vector.h>

__global__
void thekernel(int *data){
  if (threadIdx.x == 0)
    printf("the kernel says hello\n");

  data[threadIdx.x] = threadIdx.x * 2;
}

void Kernel::callKernel(){

  thrust::device_vector<int> D2;
  D2.resize(11);
  int * raw_ptr = thrust::raw_pointer_cast(&D2[0]);

  printf("Kernel::callKernel called\n");
  thekernel <<< 1, 10 >>> (raw_ptr);

  cudaThreadSynchronize();
  cudaError_t code = cudaGetLastError();
  if (code != cudaSuccess) {
    std::cout << "Cuda error: " << cudaGetErrorString(code) << " after callKernel!" << std::endl;
  }

  for (int i = 0; i < D2.size(); i++)
  std::cout << "Kernel D[" << i << "]=" << D2[i] << std::endl;
}

内核2.cuh:

#ifndef __KERNEL2_CUH__
#define __KERNEL2_CUH__
  class Kernel2{
  public:
    void callKernel2();
  };
#endif

内核2.cu

#include "kernel2.cuh"
#include <stdio.h>
#include <iostream>
#include <thrust/device_vector.h>

__global__
void thekernel2(int *data2){
  if (threadIdx.x == 0)
    printf("the kernel2 says hello\n");

  data2[threadIdx.x] = threadIdx.x * 2;
}

void Kernel2::callKernel2(){
  thrust::device_vector<int> D;
  D.resize(11);
  int * raw_ptr = thrust::raw_pointer_cast(&D[0]);
  printf("Kernel2::callKernel2 called\n");
  thekernel2 <<< 1, 10 >>> (raw_ptr);

  cudaThreadSynchronize();
  cudaError_t code = cudaGetLastError();
  if (code != cudaSuccess) {
    std::cout << "Cuda error: " << cudaGetErrorString(code) << " after callKernel2!" << std::endl;
}

  for (int i = 0; i < D.size(); i++)
  std::cout << "Kernel2 D[" << i << "]=" << D[i] << std::endl;
}

原来使用的是下面的cmake文件,但是“手动”编译时遇到了同样的问题:

nvcc -arch=sm_35 -Xcompiler -fPIC -dc kernel2.cu 
nvcc -arch=sm_35 -shared -Xcompiler -fPIC kernel2.o -o libkernel2.so
nvcc -arch=sm_35 -Xcompiler -fPIC -dc kernel.cu
nvcc -arch=sm_35 -shared -Xcompiler -fPIC kernel.o -o libkernel.so
g++ -o main main.cpp libkernel.so libkernel2.so -L/opt/cuda/current/lib64

按照某处的建议将 -cudart shared 添加到每个 nvcc 调用中会导致不同的错误:

warning: Cuda API error detected: cudaFuncGetAttributes returned (0x8)

terminate called after throwing an instance of 'thrust::system::system_error'
  what():  function_attributes(): after cudaFuncGetAttributes: invalid device function

Program received signal SIGABRT, Aborted.
0x000000313c432625 in raise () from /lib64/libc.so.6
(cuda-gdb) bt
#0  0x000000313c432625 in raise () from /lib64/libc.so.6
#1  0x000000313c433e05 in abort () from /lib64/libc.so.6
#2  0x00000031430bea7d in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib64/libstdc++.so.6
#3  0x00000031430bcbd6 in std::set_unexpected(void (*)()) () from /usr/lib64/libstdc++.so.6
#4  0x00000031430bcc03 in std::terminate() () from /usr/lib64/libstdc++.so.6
#5  0x00000031430bcc86 in __cxa_rethrow () from /usr/lib64/libstdc++.so.6
#6  0x00007ffff7d600eb in thrust::detail::vector_base<int, thrust::device_malloc_allocator<int> >::append(unsigned long) () from ./libkernel.so
#7  0x00007ffff7d5f740 in thrust::detail::vector_base<int, thrust::device_malloc_allocator<int> >::resize(unsigned long) () from ./libkernel.so
#8  0x00007ffff7d5b19a in Kernel::callKernel() () from ./libkernel.so
#9  0x00000000004006f8 in main ()

CMakeLists.txt:请根据您的环境进行调整

cmake_minimum_required(VERSION 2.6.2)

project(Cuda-project)

set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake/cuda" ${CMAKE_MODULE_PATH})

SET(CUDA_TOOLKIT_ROOT_DIR "/opt/cuda/current")

SET(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS}  -gencode arch=compute_52,code=sm_52)

find_package(CUDA REQUIRED)
link_directories(${CUDA_TOOLKIT_ROOT_DIR}/lib64)

set(CUDA_SEPARABLE_COMPILATION ON)

set(BUILD_SHARED_LIBS ON)

list(APPEND CUDA_NVCC_FLAGS -Xcompiler -fPIC)

CUDA_ADD_LIBRARY(kernel
  kernel.cu
  )

CUDA_ADD_LIBRARY(kernel2
  kernel2.cu
)

cuda_add_executable(rdctest main.cpp)
TARGET_LINK_LIBRARIES(rdctest kernel kernel2 cudadevrt)

关于我的系统:

Fedora 23 
kernel: 4.4.2-301.fc23.x86_64
Nvidia Driver: 361.28 
Nvidia Toolkit: 7.5.18
g++: g++ (GCC) 5.3.1 20151207 (Red Hat 5.3.1-2)

转载于:

CentOS release 6.7 (Final)
Kernel: 2.6.32-573.8.1.el6.x86_64
Nvidia Driver: 352.55
Nvidia Toolkit: 7.5.18
g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
glibc 2.12
cmake to 3.5

最佳答案

显然,这与使用的 cuda 运行时有关:共享的还是静态的。

我稍微修改了您的示例:我没有构建两个共享库并将它们分别链接到可执行文件,而是创建了两个静态库,它们一起链接到一个共享库,而那个共享库又链接到可执行文件。

此外,这是一个更新的 CMake 文件,它使用新的 (>= 3.8) 本地 CUDA 语言支持。

cmake_minimum_required(VERSION 3.8)
project (CudaSharedThrust CXX CUDA)

string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_61,code=compute_61")

if(BUILD_SHARED_LIBS)
  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()

add_library(kernel STATIC kernel.cu)
set_target_properties(kernel PROPERTIES CUDA_SEPARABLE_COMPILATION ON)

add_library(kernel2 STATIC kernel2.cu)
set_target_properties(kernel2  PROPERTIES CUDA_SEPARABLE_COMPILATION ON)

add_library(allkernels empty.cu) # empty.cu is an empty file
set_target_properties(allkernels PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
target_link_libraries(allkernels kernel kernel2)


add_executable(rdctest main.cpp)
set_target_properties(rdctest PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
target_link_libraries(rdctest allkernels)

在没有任何 CMake 标志(静态构建)的情况下构建它,构建成功并且程序运行。

使用 -DBUILD_SHARED_LIBS=ON 构建,程序可以编译,但它会崩溃并出现与您相同的错误。

建筑用

cmake .. -DBUILD_SHARED_LIBS=ON -DCMAKE_CUDA_FLAGS:STRING="--cudart shared"

编译,并实际运行!因此出于某种原因,此类事情需要共享 CUDA 运行时。

另请注意,从 2 个 SO 到 1 个 SO 中的 2 个静态库的步骤是必要的,否则程序将因 hrust::system::system_error 而崩溃。

然而,这是意料之中的,因为 NVCC 实际上在设备链接期间忽略了共享对象文件:http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#libraries

关于cuda & rdc & thrust in multiple shared objects results in registerEntry Function 中的 SIGSEGV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37526858/

相关文章:

python - OpenCV Python 链接器错误

c++ - 当数据在设备中时,有什么方法可以将 thrust 与 cufftComplex 数据类型一起使用?

c++ - 是否存在一些 thrust::device_vector 等效库,以在 CUDA 内核中使用?

c++ - CUDA 8 编译错误 -std=gnu++11

cuda - CUDA核心和CPU核心有什么区别?

c++ - 在这种情况下,为什么编译器会抛出 “undefined reference to…”错误?

sql - 如何配置 CMake 目标或命令来预处理 C 文件?

cuda - 主机到设备的内存复制吞吐量低

c++ - 如何从传递的数组中正确构造 CUSP coo 矩阵

c - 避免 MISD 类型操作的 CUDA 线程发散