我有一个由2个CUDA文件组成的简单脚本: main.cu 和 kernel.cu 。他们的目标是计算2个向量的总和。
// main.cu
#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>
#include <cuda.h>
#include "kernel.cu"
int main(){
/* Error code to check return values for CUDA calls */
cudaError_t err = cudaSuccess;
srand(time(NULL));
int count = 100;
int A[count], B[count];
int *h_A, *h_B;
h_A = A; h_B = B;
int i;
for(i=0;i<count;i++){
*(h_A+i) = rand() % count; /* Oppure: h_A[i] = rand() % count; */
*(h_B+i) = rand() % count; /* Oppure: h_B[i] = rand() % count; */
}
/* Display dei vettori A e B. */
printf("\nPrimi cinque valori di A = ");
for(i=0;i<4;i++){printf("%d ", A[i]);}
printf("\nPrimi cinque valori di B = ");
for(i=0;i<4;i++){printf("%d ", B[i]);}
int *d_A, *d_B;
err = cudaMalloc((void**)&d_A, count*sizeof(int));
if (err != cudaSuccess){fprintf(stderr, "Failed to allocate device vector A (error code %s)! \n", cudaGetErrorString(err));exit(EXIT_FAILURE);}
err = cudaMalloc((void**)&d_B, count*sizeof(int));
if (err != cudaSuccess){fprintf(stderr, "Failed to allocate device vector A (error code %s)! \n", cudaGetErrorString(err));exit(EXIT_FAILURE);}
err = cudaMemcpy(d_A, A, count*sizeof(int), cudaMemcpyHostToDevice);
if (err != cudaSuccess){fprintf(stderr, "Failed to copy vector A from host to device (error code %s)!\n", cudaGetErrorString(err));exit(EXIT_FAILURE);}
err = cudaMemcpy(d_B, B, count*sizeof(int), cudaMemcpyHostToDevice);
if (err != cudaSuccess){fprintf(stderr, "Failed to copy vector A from host to device (error code %s)!\n", cudaGetErrorString(err));exit(EXIT_FAILURE);}
int numThreads = 256;
int numBlocks = count/numThreads + 1;
AddInts<<<numBlocks,numThreads>>>(d_A,d_B); err = cudaGetLastError();
err = cudaMemcpy(A, d_A, count*sizeof(int), cudaMemcpyDeviceToHost);
if (err != cudaSuccess){fprintf(stderr, "Failed to copy vector C from device to host (error code %s)!\n", cudaGetErrorString(err));exit(EXIT_FAILURE);}
err = cudaFree(d_A);
if (err != cudaSuccess){fprintf(stderr, "Failed to free device vector A (error code %s)!\n", cudaGetErrorString(err));exit(EXIT_FAILURE);}
err = cudaFree(d_B);
if (err != cudaSuccess){fprintf(stderr, "Failed to free device vector A (error code %s)!\n", cudaGetErrorString(err));exit(EXIT_FAILURE);}
printf("\nPrimi cinque valori di A = ");
for(i=0;i<4;i++){printf("%d ", A[i]);}
printf("\n");
return 0;}
这里有 kernel.cu 文件:
// kernel.cu
__device__ int get_global_index(){
return (blockIdx.x * blockDim.x) + threadIdx.x;
}
__global__ void AddInts(int *a, int *b){
int ID = get_global_index();
*(a+ID) += *(b+ID);
}
我100%确定 main.cu 脚本是正确的;我也知道我可以直接在主脚本中添加内核,但这不是我测试的意图;我也知道我可以摆脱__device__
函数并将其直接放在__global__
内部,但这也不是我的意图。
当我通过在终端中键入nvcc main.cu kernel.cu
来编译测试时,我收到以下错误消息:
/tmp/tmpxft_0000248b_00000000-30_kernel.o: In function `get_global_index()':
tmpxft_0000248b_00000000-8_kernel.cudafe1.cpp:(.text+0x15): multiple definition of ` get_global_index()'
/tmp/tmpxft_0000248b_00000000-21_main.o:tmpxft_0000248b_00000000-3_main.cudafe1.cpp:(.text+0x15): first defined here
/tmp/tmpxft_0000248b_00000000-30_kernel.o: In function `__device_stub__Z7AddIntsPiS_(int*, int*)':
tmpxft_0000248b_00000000-8_kernel.cudafe1.cpp:(.text+0x7c): multiple definition of `__device_stub__Z7AddIntsPiS_(int*, int*)'
/tmp/tmpxft_0000248b_00000000-21_main.o:tmpxft_0000248b_00000000-3_main.cudafe1.cpp:(.text+0x68e): first defined here
/tmp/tmpxft_0000248b_00000000-30_kernel.o: In function `AddInts(int*, int*)':
tmpxft_0000248b_00000000-8_kernel.cudafe1.cpp:(.text+0xe5): multiple definition of `AddInts(int*, int*)'
/tmp/tmpxft_0000248b_00000000-21_main.o:tmpxft_0000248b_00000000-3_main.cudafe1.cpp:(.text+0x6f7): first defined here
collect2: error: ld returned 1 exit status
我认为错误是由名为 get_global_index()的设备函数的定义引起的,但我不明白它的错误;有没有人知道它出了什么问题?
答案 0 :(得分:4)
两个选项:
nvcc main.cu
)它已经提取kernel.cu
,因为你已经包含它了。请勿在{{1}}中加入kernel.cu
。
当您在main.cu
中包含kernel.cu
(和将两个文件传递给编译器)时,它会导致编译器编译该代码(kernel.cu)两次,一旦编译main.cu
,一次编译main.cu
。如果选择此选项,则需要在kernel.cu
中为AddInts
内核提供原型(前向引用),可能包含只包含该原型的头文件。在更一般的情况下,如果您将内容分散到更多文件中,则可能需要将main.cu
添加到编译命令行,如果您的文件具有-rdc=true
引用__global__
的函数例如,其他文件中的函数。