c++ - 尝试链接从 CUDA 对象构建的共享库时出现 undefined symbol

标签 c++ linux cuda gnu-make nvcc

我正在尝试从几个 .cu 源文件和一个非常简单的 C++ main(从其中一个 .cu 文件调用函数)构建一个简单的应用程序。我正在从编译的 .cu 文件创建一个共享库(.so 文件)。我发现一切构建都没有问题,但是当我尝试运行应用程序时,我收到链接器 undefined symbol 错误,其中包含我从 main() 调用的 .cu 函数的损坏名称。如果我构建一个静态库,我的应用程序运行得很好。这是我设置的 makefile:

.PHONY: clean
NVCCFLAGS = -std=c++11 --compiler-options '-fPIC'
CXXFLAGS = -std=c++11
HLIB = libhello.a
SHLIB = libhello.so
CUDA_OBJECTS = bridge.o add.o

all: driver

%.o :: %.cu
    nvcc -o $@ $(NVCCFLAGS) -c -I. $<

%.o :: %.cpp
    c++ $(CXXFLAGS) -o $@ -c -I. $<

$(HLIB): $(CUDA_OBJECTS)
    ar rcs $@ $^

$(SHLIB): $(CUDA_OBJECTS)
    nvcc $(NVCCFLAGS) --shared  -o $@ $^

#driver : driver.o $(HLIB)
#   c++ -std=c++11 -fPIC -o $@ driver.o -L. -lhello -L/usr/local/cuda-10.1/targets/x86_64-linux/lib -lcudart

driver : driver.o $(SHLIB)
    c++ -std=c++11 -fPIC -o $@ driver.o -L. -lhello

clean:
    -rm -f driver *.o *.so *.a

这里是 makefile 作为素材的各种源文件。 添加.cu:

__global__ void add(int n, int* a, int* b, int* c) {
    int index = threadIdx.x;
    int stride = blockDim.x;

    for (int ii = index; ii < n; ii += stride) {
        c[ii] = a[ii] + b[ii];
    }
}

添加.h:

extern __global__ void add(int n, int* a, int* b, int* c);

bridge.cu:

#include <iostream>
#include "add.h"

void bridge() {
    int N = 1 << 16;
    int blockSize = 256;
    int numBlocks = (N + blockSize - 1)/blockSize;

    int* a;
    int* b;
    int* c;

    cudaMallocManaged(&a, N*sizeof(int));
    cudaMallocManaged(&b, N*sizeof(int));
    cudaMallocManaged(&c, N*sizeof(int));

    for (int ii = 0; ii < N; ii++) {
        a[ii] = ii;
        b[ii] = 2*ii;
    }

    add<<<numBlocks, blockSize>>>(N, a, b, c);

    cudaDeviceSynchronize();

    for (int ii = 0; ii < N; ii++) {
        std::cout << a[ii] << " + " << b[ii] << " = " << c[ii] << std::endl;
    }

    cudaFree(a);
    cudaFree(b);
    cudaFree(c);
}

bridge.h:

extern void bridge();

驱动程序.cpp:

#include "bridge.h"

int main() {
    bridge();
    return 0;
}

我对 cuda 很陌生,所以我希望这就是我做错的地方。我尝试过使用 extern“C” 声明,但这似乎只是将“ undefined symbol ”错误从运行时移至构建时。

我熟悉以 undefined symbol 结束的各种方式,并且我提到了我已经执行过的各种实验(静态链接、外部“C”声明),这些实验让我认为这个问题并没有通过提议的重复问题得到解决。

我无法解析的符号是_Z6bridgev

在我看来,链接器应该能够解析该符号。如果我可以在 driver.o 上 nm,我会看到:

0000000000000000 T main
                 U _Z6bridgev

如果我在 libhello.so 上运行 nm,我会看到:

0000000000006e56 T _Z6bridgev

最佳答案

当 Robert Crovella 能够让我的示例在他的机器上运行时,而我无法让他的示例在我的机器上运行时,我开始意识到我的问题与 cuda 或 nvcc 无关。事实上,对于共享库,加载程序必须在运行时解析符号,而我的共享库并不位于“众所周知的位置”。我刚才构建了一个简单的测试用例,纯粹使用c++源代码,并重复了我的失败。将 libhello.so 复制到 /usr/local/lib 后,我就能够成功运行 driver。所以,如果这是人民的意愿,我可以结束我最初的问题。

关于c++ - 尝试链接从 CUDA 对象构建的共享库时出现 undefined symbol ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56637075/

相关文章:

linux - 进程(任务)的 CPU 使用率 Linux 内核

linux - 无法找到 Apache .conf 文件

performance - 两个连续的内核还是全网格协作组同步?

c++ - libcUrl 错误请求。似乎没有发送 POST 正文,只有标题

c++ - PPL - 许可证和链接信息

linux - 回声 "string"| xclip -selection clipboard ,复制 'string' 但也添加了一个新行。如何解决这个问题?

Cuda C - 链接器错误 - undefined reference

cuda - 在内核中调用 cublas

c++ - glCallList 上的 OpenMP 段错误的 GLFW3(以及 glfw 中的其他地方)

c++ - 可变参数模板推导错误