LNK2005在CUDA标头(.cuh)文件中使用常量内存时出错

时间:2014-09-08 09:35:59

标签: c++ cuda

我有一个包含两个常量float数组的CUDA Header(.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];
}

ext.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);
}

构建失败并输出以下错误:

1>ext.obj : error LNK2005: "float * d_array1" (?d_array1@@3PAMA) already defined in obj1.cu.obj
1>ext.obj : error LNK2005: "float * d_array2" (?d_array2@@3PAMA) already defined in obj1.cu.obj

在你问之前,是的,我曾尝试过使用包含保护而不是编译指示一次,它仍会输出相同的错误。

包含obj1.cuh的防护版

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

1 个答案:

答案 0 :(得分:1)

问题正是链接器告诉你的:变量是定义多个translation units

当预处理器包含头文件时,它会将标题中的文本粘贴到#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或标头包含防护措施可防止在同一个翻译单元中多次包含头文件。