尝试链接从CUDA对象生成的共享库时未定义符号 我正在尝试从一对CU源文件和一个非常简单的C++主程序构建一个简单的应用程序,它调用一个Cu文件中的函数。我正在从编译的.cu文件创建一个共享库(.so文件)。我发现一切都可以顺利构建,但是当我尝试运行应用程序时,我得到了一个链接器未定义的符号错误,我从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

尝试链接从CUDA对象生成的共享库时未定义符号 我正在尝试从一对CU源文件和一个非常简单的C++主程序构建一个简单的应用程序,它调用一个Cu文件中的函数。我正在从编译的.cu文件创建一个共享库(.so文件)。我发现一切都可以顺利构建,但是当我尝试运行应用程序时,我得到了一个链接器未定义的符号错误,我从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,c++,linux,cuda,gnu-make,nvcc,C++,Linux,Cuda,Gnu Make,Nvcc,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

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);
}
driver.cpp:

#include "bridge.h"

int main() {
    bridge();
    return 0;
}
我是cuda的新手,所以我想这就是我做错事情的地方。我曾经尝试过使用extern“C”声明,但这似乎只是将“undefined symbol”错误从运行时转移到构建时

我熟悉以未定义的符号结束的各种方式,并且我提到了我已经执行的各种实验(静态链接、外部“C”声明),这些实验使我认为这个问题不会通过提出的重复问题得到解决

我的未解析符号是
\u 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
,我就能够成功地运行
驱动程序。所以,如果这是人民的意愿,我可以结束我最初的问题

引用的dup是问题的一部分,但我不认为它是本案的控制问题。我认为OP需要帮助修复makefile,并解释如何编写配方,以及如何包含变量,如
LDFLAGS
LDLIBS
。重新打开。@jww谢谢您的评论。更具体地说,我是否在构建共享库时未正确使用nvcc,或者在link命令中缺少一些标志?我再次编辑了我的问题,以表明我相信我构建的库具有driver.o需要解析的符号。
echo\u Z6bridgev | c++filt
产生
bridge()
bridge()
函数在哪个库中,库位于哪里?(问题在于制作makefile的方式;但是缺少一些信息来给您提供完整的答案)。我根据您在这里展示的内容组装了一个完整的项目,没有对makefile进行任何修改,其中driver.cpp与您描述的完全相同,其他所有需要的文件(bridge.cu、add.cu等)。它可以编译,代码可以正确运行。下面是您应该做的。不要运出更多的碎片。相反,发布您认为完整的测试用例。然后,在您的计算机上重新创建一个目录,其中没有任何内容。然后从您发布的文件复制到该目录中,并运行Makefile。换句话说,如果我想看到问题,我会做什么。当该过程产生问题时,您将有理由相信您已经提供了适当的测试用例。是的,这需要努力。
#include "bridge.h"

int main() {
    bridge();
    return 0;
}
0000000000000000 T main
                 U _Z6bridgev
0000000000006e56 T _Z6bridgev