【问题标题】:LNK2005 Error when using Constant Memory in CUDA Header (.cuh) File在 CUDA 头文件 (.cuh) 文件中使用常量内存时出现 LNK2005 错误
【发布时间】:2014-09-08 09:35:59
【问题描述】:

我有一个包含两个常量浮点数组的 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];
}

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

【问题讨论】:

    标签: c++ cuda


    【解决方案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 或标头包含防护可防止标头文件多次包含在同一翻译单元中。

    【讨论】:

    • 谢谢约阿希姆。但我不明白的是,当我只在 .cu 文件中定义两个数组时,如果 .cpp 文件未在该文件中定义,它如何能够使用该数组?例如,我可以在 cudaMemcpyToSymbol 函数中使用数组而不会出错。
    • @JonnyPringle 这就是头文件中的声明的用途。
    猜你喜欢
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 2010-12-30
    • 1970-01-01
    • 1970-01-01
    • 2017-09-08
    • 2018-10-24
    • 1970-01-01
    相关资源
    最近更新 更多