CUDA / C ++ - 链接错误:未定义引用

时间:2016-03-09 08:02:58

标签: c++ gcc cuda g++ nvcc

我是一个新手,正在寻找帮助,使用g ++将一些已编译的CUDA目标代码链接到C ++项目。已经发布了一些以前的问题和解决方案(herehere),但没有一个对我有用,我似乎无法弄清楚原因。不幸的是,我为此坚持使用Windows。

我正在努力工作的简单示例如下所示:

// kernel.h
int cuda_vec_add(float *h_a, float *h_b, float *h_c, int n);

添加两个向量的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;
}

调用CUDA函数的c ++代码。

// main.cpp
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <kernel.h>

using namespace std;


int main() {
    const int n = 5;
    float h_A[n] = { 0., 1., 2., 3., 4. };
    float h_B[n] = { 5., 4., 3., 2., 1. };
    float h_C[n];

    cuda_vec_add(h_A, h_B, h_C, n);

    printf("{ 0.0, 1.0, 2.0, 3.0, 4.0 } + { 5.0, 4.0, 3.0, 2.0, 1.0 } = { %0.01f, %0.01f, %0.01f, %0.01f, %0.01f }\n",
        h_C[0], h_C[1], h_C[2], h_C[3], h_C[4]);

    cin.get();

    return 0;
}

我首先使用nvcc:

将CUDA代码编译为“kernel.o”
nvcc -I. -arch=sm_30 -c kernel.cu -o kernel.o

这似乎工作正常。但是当我尝试将它链接到我的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工具包7.5和Visual Studio 2013以及gcc版本5.2.0。

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

  • 使用nvcc编译所有内容。这样可以正常工作,除非它不符合我的项目要求。

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

  • 其他一些效率较低的事情。

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

1 个答案:

答案 0 :(得分:1)

如果问题确实是g ++ anc 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_vec_add的条目如下所示:

[302](sec  5)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x0000000000000050 cuda_vec_add

与您的参赛作品相比,没有名称错位。您是否正确应用了extern "C" {}块?

并仔细检查位数。我最初链接到x86库和g++只抱怨不解决cudaMemcpy但没有关于libs不兼容的事实。 objdump可以帮助您 - 它在第一行打印架构。例如,当我运行objdump kernel.obj -t时,第一行是

kernel.obj:     file format pe-x86-64

所以你可以检查你的目标文件是否匹配。