2

这是我第一次处理比简单的 write-single-source-file-and-compile 例程稍微复杂的 CUDA 项目。正如预期的那样,我遇到了 C 标头的一些问题,即重复符号。

根据链接器,在多个文件中包含以下头文件会产生冲突.cu

env_vars.h

#ifndef ENV_VARS_H_
#define ENV_VARS_H_

/*** GLOBAL VARIABLES ***/
unsigned int h_n_osc;
__device__ unsigned int d_n_osc;

/*** CONSTANTS ***/
const double OMEGA_0 = 6.447421494058077e+09;

/* other constants defined in the middle */

#endif

多显卡

#include "env_vars.h"
/* assigns h_n_osc */

adm_matrix.cu

#include "env_vars.h"
/* uses h_n_osc */

在 Nsight Eclipse Edition 中构建项目会导致链接器抱怨h_n_osc变量被定义了两次:

duplicate symbol _h_n_osc in:
    ./adm_matrix.o
    ./multigpu.o
ld: 1 duplicate symbol for architecture x86_64

通过 Internet 搜索,我意识到将变量的声明移动h_n_oscmultigpu.cu并将其重新声明为extern变量adm_matrix.cu(以及以后我可能需要它的任何地方)可以解决问题,事实上它确实如此

问题解决了,但我想更深入地研究一下:

  1. 为什么链接器也不抱怨d_n_osc变量?为什么常数(例如OMEGA_0)同样不是问题?
  2. 这是否意味着不能将全局变量放在头文件中?
  3. 最让我困惑的是,互联网上的一些消息来源指出,重复符号错误只会在头文件包含变量定义时发生,而它的简单声明不应该构成问题。我很难相信这一点的原因是即使我的标题只包含一个声明,我也面临着这个问题!我错过了什么吗?

提前感谢您的耐心等待,伙计们!

4

1 回答 1

9

头文件通常应该包含声明性代码。h_n_osc应该在这里声明,而不是定义

extern unsigned int h_n_osc;

在您的至少一个模块中,或者在它自己的一个新模块中,您需要一个定义;例如:

env_vars.cu

#include "env_vars.h"
unsigned int h_n_osc;

然后链接那个。或者,您当然可以将定义放在现有模块 multigpu.cu 或 adm_matrix.cu 之一中。

我不确定CUDA__device__扩展的语义,虽然它可能链接,但不一定正确;您最终可能会导致每个模块都引用设备变量的单独副本;可能也有必要对其进行限定extern这个问题似乎处理了这个问题。

于 2014-12-02T19:59:41.173 回答