CUDA/C++;-链接错误:未定义对的引用 我是新手,希望通过使用G++将一些编译的CUDA对象代码链接到C++项目。之前已经有一些问题和解决方案发布(和),但没有一个对我有效,我似乎不明白为什么。不幸的是,我一直在使用Windows来完成这个任务

CUDA/C++;-链接错误:未定义对的引用 我是新手,希望通过使用G++将一些编译的CUDA对象代码链接到C++项目。之前已经有一些问题和解决方案发布(和),但没有一个对我有效,我似乎不明白为什么。不幸的是,我一直在使用Windows来完成这个任务,c++,gcc,cuda,g++,nvcc,C++,Gcc,Cuda,G++,Nvcc,我正在尝试工作的简单示例如下所示: // kernel.h int cuda_vec_add(float *h_a, float *h_b, float *h_c, int n); [302](sec 5)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000000000000050 cuda_vec_add CUDA代码添加两个向量 // kernel.cu #include <kernel.h> __global__ void vec_add_k

我正在尝试工作的简单示例如下所示:

// kernel.h
int cuda_vec_add(float *h_a, float *h_b, float *h_c, int n);
[302](sec  5)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x0000000000000050 cuda_vec_add
CUDA代码添加两个向量

// kernel.cu
#include <kernel.h>

__global__ void vec_add_kernel(float *a, float *b, float *c, int n) {
    int i = threadIdx.x + blockDim.x * blockIdx.x;
    if (i < n) c[i] = a[i] + b[i];
}

int cuda_vec_add(float *h_a, float *h_b, float *h_c, int n) {
    float *d_a, *d_b, *d_c;

    cudaMalloc(&d_a, n*sizeof(float));
    cudaMalloc(&d_b, n*sizeof(float));
    cudaMalloc(&d_c, n*sizeof(float));

    cudaMemcpy(d_a, h_a, n*sizeof(float), cudaMemcpyHostToDevice);
    cudaMemcpy(d_b, h_b, n*sizeof(float), cudaMemcpyHostToDevice);

    vec_add_kernel<< <(n-1)/256+1,256>> >(d_a, d_b, d_c, n);

    cudaMemcpy(h_c, d_c, n*sizeof(float), cudaMemcpyDeviceToHost);

    cudaFree(d_a); cudaFree(d_b); cudaFree(d_c);

    return 0;
}
这似乎很有效。但是当我尝试把它链接到我的C++项目:

g++ -I. -L"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\lib\x64" main.cpp kernel.o -lcuda -lcudart
我得到以下错误:

Warning: corrupt .drectve at end of def file
C:\Users\Geoff\AppData\Local\Temp\cczu0qxj.o:main.cpp:(.text+0xbe):
undefined reference to `cuda_vec_add(float*, float*, float*, int)'
collect2.exe: error: ld returned 1 exit status
我将CUDA toolkit 7.5与Visual Studio 2013和gcc 5.2.0版一起使用

到目前为止,我已经尝试:

  • 使用nvcc编译所有内容。除了不符合我的项目要求之外,这一切都很好

  • 在nvcc中使用-dlink标志发布的解决方案。不幸的是,这返回了相同的错误

  • 其他一些生产力较低的东西


如果这是一个愚蠢的错误,我真的很抱歉,但我已经坚持了一段时间了。感谢您的帮助。

如果问题真的是g++和cl之间的名称差异导致g++根本看不到函数,请尝试在
extern“C”{}
块中定义它以强制C链接。这可能会有帮助

编辑

所以我试着做同样的事情,我能够成功地链接。让我发布我所做的,我希望这对你有所帮助

因此,我的系统上有CUDA toolkit 7.5和mingw x64(gcc 4.5.4)

我将您的代码放在您描述的三个文件中——kernel.cu、main.cpp和kernel.h,并将kernel.h改为

#pragma once

extern "C" 
{
int cuda_vec_add(float *h_a, float *h_b, float *h_c, int n);
}
然后我做到了

nvcc kernel.cu -c -o kernel.obj
g++.exe -c main.cpp -o main.obj
g++.exe  main.obj kernel.obj "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\lib\Win32\cuda.lib" "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\lib\Win32\cudart.lib" -o main.exe
很可能得到了
main.exe
。奇怪的是,nvcc自动调用64位编译器——如果您使用32位g++并且nvcc生成64位对象文件,那么这可能是您的问题,但这取决于系统的配置

我还使用了
objdump
转储
kernel.obj
文件,我的
cuda\u vec\u add
条目如下所示:

// kernel.h
int cuda_vec_add(float *h_a, float *h_b, float *h_c, int n);
[302](sec  5)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x0000000000000050 cuda_vec_add
如果与您的条目相比较,则没有名称损坏。您是否正确应用了
extern“C”{}

并再次检查咬合度。我最初链接到x86 libs,而
g++
只是抱怨没有解决
cudaMemcpy
,但没有抱怨libs不兼容的事实
objdump
可以帮助您实现这一点——它在第一行打印架构。例如,当我运行
objdump kernel.obj-t
时,第一行是

kernel.obj:     file format pe-x86-64

因此,如果两个对象文件确实匹配,您可以检查它们。

要了解这是否是名称损坏问题,您可以在
kernel.o
上运行
nm
,查看
cuda\u vec\u add
函数的外观吗?此外,关于损坏的警告似乎很奇怪。您不能在带有CUDA的Windows平台上使用g++或GNU工具。这是一种不受支持的配置。有关受支持的编译器和配置,请参阅Windows安装指南。基本上,你必须使用VisualStudio和MS C++编译器C.ExeIT,看起来罗伯特是正确的,这是一个使用G++与Windows中的CUDA的问题。我只是在linux机器上尝试了一下,没有出现任何错误。谢谢你的帮助。看来这个问题不是因为名字弄错引起的。在kernel.cu中的主机代码周围添加一个extern“C”{}块并没有改变错误。看起来Robert是对的,我使用的工具是Windows特有的问题。谢谢您的帮助。@GeoffM well Robert说的没错,Visual Studio是官方支持的工具包,但是当混合使用g++和msvc时,会出现的主要问题是名称混乱。出于好奇,可以从内核对象文件中转储符号以查看其中的内容吗?好的,当然可以。我不知道如何理解
kernel.o
上的
nm
的输出,但是我已经将完整的输出粘贴到了这里-。引用“cuda_vec_add”函数的行如下-
000000000000000 c p$pdata$?cuda_vec_add@@YAHPEAM00H@Z
@GeoffM不顾被否决的人(是的,我知道我在宣传不受支持的机制,但是嘿-如果这个人需要使用g++而他不能做任何其他事情-这就是为什么我们在这里提供帮助),我自己尝试过这样做,并且成功了,我将编辑我的帖子,希望这对我有所帮助。如果被否决的人看到这一点,我真的很想知道被否决的原因。