C++ 在CUDA头(.cuh)文件中使用常量内存时发生LNK2005错误

C++ 在CUDA头(.cuh)文件中使用常量内存时发生LNK2005错误,c++,cuda,C++,Cuda,我有一个CUDA头(.cuh)文件,其中包含两个常量浮点数组。有两个文件包含此标头,一个是尝试复制到此常量内存的CPP文件,另一个是尝试使用此常量内存的CUDA文件。这三个文件都在一个项目中,应该编译成DLL 我尝试用以下代码简化事情: obj1.cuh #pragma once __constant__ float d_array1[5]; __constant__ float d_array2[5]; obj1.cu #include "obj1.cuh" //do random st

我有一个CUDA头(.cuh)文件,其中包含两个常量浮点数组。有两个文件包含此标头,一个是尝试复制到此常量内存的CPP文件,另一个是尝试使用此常量内存的CUDA文件。这三个文件都在一个项目中,应该编译成DLL

我尝试用以下代码简化事情:

obj1.cuh

#pragma once

__constant__ float d_array1[5];
__constant__ float d_array2[5];
obj1.cu

#include "obj1.cuh"

//do random stuff
__global__ void kernel(float * d_array1, float * d_array2) {
  int id = threadIdx.x;
  float sum = d_array1[i] + d_array2[i];
}
分机cpp

#include "obj1.cuh"

void function(float * array1, float * array2) {
  cudaMemcpyToSymbol(d_array1, array1, sizeof(float)*5);
  cudaMemcpyToSymbol(d_array2, array2, sizeof(float)*5);

  kernel<<<1,5>>>(d_array1,d_array2);
}
在您询问之前,是的,我曾经尝试过使用include-guard而不是pragma,但它仍然输出相同的错误

包括obj1.cuh的防护版本

#ifndef CONSTANTARRAYS
#define CONSTANTARRAYS
__constant__ float d_array1[5];
__constant__ float d_array2[5];
#endif

问题正是链接器告诉您的:变量是以多个形式定义的

当预处理器包含头文件时,它会将头文件中的文本粘贴到
#include
指令所在的位置,这意味着两个生成的对象文件都有变量的定义

您应该做的是只在头文件中声明变量,然后在单个源文件中定义它们。要将定义更改为声明,最简单的方法是在
extern
关键字前面加上前缀:

#pragma once

extern __constant__ float d_array1[5];
extern __constant__ float d_array2[5];
然后在单个源文件中有旧的定义:

__constant__ float d_array1[5];
__constant__ float d_array2[5];

#pragma once
或头文件包含保护可防止头文件多次包含在同一翻译单元中。

谢谢Joachim。但我不明白的是,当我在.cu文件中只定义了两个数组时,.cpp文件在该文件中没有定义的情况下如何使用数组?例如,我可以使用cudaMemcpyToSymbol函数中的数组,而不会出现错误。@JonnyPringle头文件中的声明就是为了这个。
__constant__ float d_array1[5];
__constant__ float d_array2[5];