Geo*_*f M 5 c++ gcc cuda g++ nvcc
我是一个新手,正在寻找帮助,使用g ++将一些已编译的CUDA目标代码链接到C++项目.已经有一些以前的问题和解决方案(这里和这里),但没有一个对我有用,我似乎无法弄清楚为什么.不幸的是,我为此坚持使用Windows.
我正在努力工作的简单示例如下所示:
// kernel.h
int cuda_vec_add(float *h_a, float *h_b, float *h_c, int n);
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
和c ++代码调用CUDA函数.
// 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;
}
Run Code Online (Sandbox Code Playgroud)
我首先使用nvcc将CUDA代码编译为"kernel.o":
nvcc -I. -arch=sm_30 -c kernel.cu -o kernel.o
Run Code Online (Sandbox Code Playgroud)
这似乎工作正常.但是当我尝试将它链接到我的C++项目时:
g++ -I. -L"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\lib\x64" main.cpp kernel.o -lcuda -lcudart
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
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
Run Code Online (Sandbox Code Playgroud)
我正在使用CUDA工具包7.5与Visual Studio 2013和gcc版本5.2.0.
到目前为止,我已经尝试过:
使用nvcc编译所有内容.这工作正常,但它不符合我的项目的要求.
此处使用nvcc中的-dlink标志发布解决方案.不幸的是,这返回了同样的错误.
其他一些效率较低的东西.
真的很抱歉,如果这最终是一个愚蠢的错误,但我已经坚持了一段时间.谢谢你的帮助.
如果问题确实是 g++ 和 c cl 之间的名称修改差异导致 g++ 根本看不到该函数,请尝试在块内定义它extern "C" {}以强制 C 链接。这可能有帮助。
编辑
所以我尝试做同样的事情,并且能够成功链接。让我发布我所做的事情,希望这对您有所帮助。
所以我的系统上有 CUDA 工具包 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);
}
Run Code Online (Sandbox Code Playgroud)
然后我做了
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
Run Code Online (Sandbox Code Playgroud)
并高兴地得到了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
Run Code Online (Sandbox Code Playgroud)
与您的条目相比,没有名称损坏。您是否正确应用了该extern "C" {}块?
并且还要仔细检查位数。我最初链接到 x86 库,g++只是抱怨没有解决cudaMemcpy,但对库不兼容的事实没有任何抱怨。objdump可以帮助你——它在第一行打印架构。例如,当我运行objdump kernel.obj -t第一行时
kernel.obj: file format pe-x86-64
Run Code Online (Sandbox Code Playgroud)
这样您就可以检查两个目标文件是否匹配。
| 归档时间: |
|
| 查看次数: |
4325 次 |
| 最近记录: |