c++ - cuda 共享库链接 : undefined reference to cudaRegisterLinkedBinary

标签 c++ cuda makefile shared-libraries nvcc

目标:

  1. 创建一个包含我的 CUDA 内核的共享库,该内核具有无 CUDA 包装器/ header 。
  2. 为共享库创建一个test 可执行文件。

问题

  1. 共享库 MYLIB.so 似乎可以正常编译。 (没问题)。
  2. 链接错误:

./libMYLIB.so:对 __cudaRegisterLinkedBinary_39_tmpxft_000018cf_00000000_6_MYLIB_cpp1_ii_74c599a1 的 undefined reference

简化的 makefile:

libMYlib.so :  MYLIB.o
    g++  -shared  -Wl,-soname,libMYLIB.so  -o libMYLIB.so    MYLIB.o  -L/the/cuda/lib/dir  -lcudart


MYLIB.o : MYLIB.cu   MYLIB.h
    nvcc  -m64   -arch=sm_20 -dc  -Xcompiler '-fPIC'  MYLIB.cu  -o  MYLIB.o  -L/the/cuda/lib/dir  -lcudart


test : test.cpp  libMYlib.so
        g++   test.cpp  -o test  -L.  -ldl -Wl,-rpath,.   -lMYLIB  -L/the/cuda/lib/dir  -lcudart

确实

nm libMYLIB.so 显示所有 CUDA api 函数都是“ undefined symbol ”:

         U __cudaRegisterFunction
         U __cudaRegisterLinkedBinary_39_tmpxft_0000598c_00000000_6_CUPA_cpp1_ii_74c599a1
         U cudaEventRecord
         U cudaFree
         U cudaGetDevice
         U cudaGetDeviceProperties
         U cudaGetErrorString
         U cudaLaunch
         U cudaMalloc
         U cudaMemcpy

所以 CUDA 不知何故没有链接到共享库 MYLIB.so 我错过了什么?


CUDA 甚至没有以某种方式链接到目标文件:

nm MYLIB.o

         U __cudaRegisterFunction
         U __cudaRegisterLinkedBinary_39_tmpxft_0000598c_00000000_6_CUPA_cpp1_ii_74c599a1
         U cudaEventRecord
         U cudaFree
         U cudaGetDevice
         U cudaGetDeviceProperties
         U cudaGetErrorString
         U cudaLaunch
         U cudaMalloc
         U cudaMemcpy

(同上)

最佳答案

这是一个按照您指出的方式创建 linux 共享对象的示例:

  1. 创建一个包含我的 CUDA 内核的共享库 无 CUDA 包装器/ header 。
  2. 为共享库创建一个测试可执行文件。

首先是共享库。构建命令如下:

nvcc -arch=sm_20 -Xcompiler '-fPIC' -dc test1.cu test2.cu
nvcc -arch=sm_20 -Xcompiler '-fPIC' -dlink test1.o test2.o -o link.o
g++ -shared -o test.so test1.o test2.o link.o -L/usr/local/cuda/lib64 -lcudart

看来你的makefile中可能漏掉了上面的第二步,但是我没有分析你的makefile是否还有其他问题。

现在,对于测试可执行文件,构建命令如下:

g++ -c main.cpp
g++ -o testmain main.o test.so

要运行它,只需执行 testmain 可执行文件,但要确保 test.so 库位于您的 LD_LIBRARY_PATH 上。

这些是我用于测试目的的文件:

测试1.h:

int my_test_func1();

test1.cu:

#include <stdio.h>
#include "test1.h"

#define DSIZE 1024
#define DVAL 10
#define nTPB 256

#define cudaCheckErrors(msg) \
    do { \
        cudaError_t __err = cudaGetLastError(); \
        if (__err != cudaSuccess) { \
            fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
                msg, cudaGetErrorString(__err), \
                __FILE__, __LINE__); \
            fprintf(stderr, "*** FAILED - ABORTING\n"); \
            exit(1); \
        } \
    } while (0)

__global__ void my_kernel1(int *data){
  int idx = threadIdx.x + (blockDim.x *blockIdx.x);
  if (idx < DSIZE) data[idx] =+ DVAL;
}

int my_test_func1(){

  int *d_data, *h_data;
  h_data = (int *) malloc(DSIZE * sizeof(int));
  if (h_data == 0) {printf("malloc fail\n"); exit(1);}
  cudaMalloc((void **)&d_data, DSIZE * sizeof(int));
  cudaCheckErrors("cudaMalloc fail");
  for (int i = 0; i < DSIZE; i++) h_data[i] = 0;
  cudaMemcpy(d_data, h_data, DSIZE * sizeof(int), cudaMemcpyHostToDevice);
  cudaCheckErrors("cudaMemcpy fail");
  my_kernel1<<<((DSIZE+nTPB-1)/nTPB), nTPB>>>(d_data);
  cudaDeviceSynchronize();
  cudaCheckErrors("kernel");
  cudaMemcpy(h_data, d_data, DSIZE * sizeof(int), cudaMemcpyDeviceToHost);
  cudaCheckErrors("cudaMemcpy 2");
  for (int i = 0; i < DSIZE; i++)
    if (h_data[i] != DVAL) {printf("Results check failed at offset %d, data was: %d, should be %d\n", i, h_data[i], DVAL); exit(1);}
  printf("Results check 1 passed!\n");
  return 0;
}

测试2.h:

int my_test_func2();

test2.cu:

#include <stdio.h>
#include "test2.h"

#define DSIZE 1024
#define DVAL 20
#define nTPB 256

#define cudaCheckErrors(msg) \
    do { \
        cudaError_t __err = cudaGetLastError(); \
        if (__err != cudaSuccess) { \
            fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
                msg, cudaGetErrorString(__err), \
                __FILE__, __LINE__); \
            fprintf(stderr, "*** FAILED - ABORTING\n"); \
            exit(1); \
        } \
    } while (0)

__global__ void my_kernel2(int *data){
  int idx = threadIdx.x + (blockDim.x *blockIdx.x);
  if (idx < DSIZE) data[idx] =+ DVAL;
}

int my_test_func2(){

  int *d_data, *h_data;
  h_data = (int *) malloc(DSIZE * sizeof(int));
  if (h_data == 0) {printf("malloc fail\n"); exit(1);}
  cudaMalloc((void **)&d_data, DSIZE * sizeof(int));
  cudaCheckErrors("cudaMalloc fail");
  for (int i = 0; i < DSIZE; i++) h_data[i] = 0;
  cudaMemcpy(d_data, h_data, DSIZE * sizeof(int), cudaMemcpyHostToDevice);
  cudaCheckErrors("cudaMemcpy fail");
  my_kernel2<<<((DSIZE+nTPB-1)/nTPB), nTPB>>>(d_data);
  cudaDeviceSynchronize();
  cudaCheckErrors("kernel");
  cudaMemcpy(h_data, d_data, DSIZE * sizeof(int), cudaMemcpyDeviceToHost);
  cudaCheckErrors("cudaMemcpy 2");
  for (int i = 0; i < DSIZE; i++)
    if (h_data[i] != DVAL) {printf("Results check failed at offset %d, data was: %d, should be %d\n", i, h_data[i], DVAL); exit(1);}
  printf("Results check 2 passed!\n");
  return 0;
}

主要.cpp:

#include <stdio.h>

#include "test1.h"
#include "test2.h"

int main(){

  my_test_func1();
  my_test_func2();
  return 0;
}

当我根据给定的命令编译并运行 ./testmain 时,我得到:

$ ./testmain
Results check 1 passed!
Results check 2 passed!

请注意,如果您愿意,您可以生成一个 libtest.so 而不是 test.so,然后您可以为测试可执行文件使用修改后的构建序列:

g++ -c main.cpp
g++ -o testmain main.o -L. -ltest

我不认为这有什么区别,但它可能是更熟悉的语法。

我确信有不止一种方法可以实现这一点。这只是一个例子。 您可能还希望查看 nvcc manual 的相关部分并查看 examples .

编辑: 我在 cuda 5.5 RC 下对此进行了测试,最后的应用程序链接步骤提示找不到 cudart 库(警告:libcudart.so.5.5.,./需要libtest.so,未找到)。然而,以下相对简单的修改(示例 Makefile)应该在 cuda 5.0 或 cuda 5.5 下工作。

生成文件:

testmain : main.cpp  libtest.so
        g++ -c main.cpp
        g++ -o testmain  -L.  -ldl -Wl,-rpath,.   -ltest -L/usr/local/cuda/lib64 -lcudart main.o

libtest.so : link.o
        g++  -shared -Wl,-soname,libtest.so -o libtest.so    test1.o test2.o link.o  -L/usr/local/cuda/lib64  -lcudart

link.o : test1.cu test2.cu   test1.h test2.h
        nvcc  -m64   -arch=sm_20 -dc  -Xcompiler '-fPIC'  test1.cu test2.cu
        nvcc  -m64   -arch=sm_20 -Xcompiler '-fPIC' -dlink test1.o test2.o -o link.o

clean :
        rm -f testmain test1.o test2.o link.o libtest.so main.o

关于c++ - cuda 共享库链接 : undefined reference to cudaRegisterLinkedBinary,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17278932/

相关文章:

c++ - 如何为节点分配名称?我在这里遗漏了什么吗?

java - 尝试运行 JCuda 示例时 java.library.path 中没有 JCudaRuntime-0.9.2-windows-x86_64

c++ - CUDA 缩减,大阵列的方法

c++ - 分析我的代码(开源)和第 3 方代码(闭源)的内存使用情况的最佳策略

c - 当隐式规则没有说明可执行文件时,make 如何从 C 源文件构建可执行文件?

c++ - "cc1plus: error: bad value (‘tigerlake’ ) 对于 ‘-march=’ 开关"编译错误

c++ - 字 rune 字的 U 前缀与字符串文字的区别是什么?

c++ - 设置 eclipse 链接器以编译和运行 GLFW 应用程序 - 如何?

c++ - 为什么没有 std::is_struct 类型特征?

module - makefile 模块在 fortran 90 中编译 gfortran