链接期间出现 CUDA 多重定义错误

CUDA multiple definition error during linking

我开始在我的一个项目中使用 CUDA 和 thrust,所以我对它的某些方面还是很陌生。我运行陷入以下问题。

我必须将要使用的 .cu 文件与一个公共头文件分开,该头文件具有它们都可以使用的结构。它是这样的:

////////Global.h
#ifndef global_h
#define global_h
struct globalParam
{
    uint64_t spaceToUse;
    globalParams() : spaceToUse(1024*1024*1024) {}
};

globalParam glParam;
#endif

第一个 .cu 文件如下所示:

////////firstcufile.cu
#ifndef firstcufile_cu
#define firstcufile_cu
#include "Global.h"

template<typename T>
QVector<T> GPUcalculateNormSq(const QVector<T>& real, const QVector<T>& imag)
{
    QVector<T> result (real.size());
    uint64_t maxSpace = glParam.spaceToUse;

    //Some Code to use thrust and using tops maxSpace bytes.

    return result;
}

template QVector<float> GPUcalculateNormSq(const QVector<float>& real, const QVector<float>& imag);
template QVector<double> GPUcalculateNormSq(const QVector<double>& real, const QVector<double>& imag);

#endif

第二个 .cu 文件如下所示:

////////secondcufile.cu
#ifndef secondcufile_cu
#define secondcufile_cu
#include "Global.h"

template<typename T>
double getMean(const T& vec)
{
    uint64_t spaceNeededOnGPU = vec.size() * sizeof (T);
    uint64_t maxSpace = glParam.spaceToUse;

    //Some code to make sure tops maxSpace bytes on GPU
    double sum = thrust::reduce(std::begin(vec), std::end(vec));
    return sum / vec.size();
}

template double getMean(const QVector<float>& vec);
#endif

现在我得到的错误是:

secondcufilecuda_d.o:(.bss+0x18): multiple definition of `glParam'
firstcufilecuda_d.o:(.bss+0x18): first defined here

上面的功能看起来很相似,但那是因为我尽量使它们尽可能简单。可以将所有内容写入单个 .cu 文件,但如果可能,我想将其拆分。

链接器我做错了什么?我正在 Qt Creator 项目中进行编译和链接。如果您需要 .pro 文件中的行来了解我如何使用 nvcc 编译器,请告诉我。

这是因为 Global.h 被多次包含并且每次包含它都提供:globalParam glParam;。这不是前向声明(即不仅仅是类型签名),而是相当于 globalParam 结构的实际实例化。然后,这会导致有两个变量都命名为 glParam(每个变量对应于 Global.h 的单独 #include),这会给您带来多个定义错误。

快速修复:如果您想共享全局变量,请尝试使用 extern(然后链接器知道它只是对 'external' 符号的引用)。

更好的解决方法:考虑重构您的代码以通过引用或指针将全局参数作为参数传递给您的函数。这样您甚至不必在 header 中声明 glParam 变量,避开整个问题并使您的代码更容易 understand/reason 讨价还价。