Duplicate symbol issue with C headers

This is my first time tackling a CUDA project that's slightly more complex than the simple write-single-source-file-and-compile routine. As expected, I'm facing some issues with C headers, namely duplicated symbols.

According to the linker, conflicts arise over the inclusion of the following header file in multiple .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

multigpu.cu

#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

Ища в интернете, я понял, что продвижение декларации h_n_osc переменная к multigpu.cu и повторно объявив его как extern переменная в adm_matrix.cu (и там, где мне это может понадобиться позже) решает проблему, что на самом деле и делает.

Проблема решена, но я бы хотел глубже взглянуть на это:

  1. Почему компоновщик не жалуется на d_n_osc переменная, а? И почему константы (такие как OMEGA_0) одинаково не проблема?
  2. Означает ли это, что невозможно разместить глобальные переменные в заголовочных файлах?
  3. Что меня больше всего озадачивает, так это то, что ряд источников в Интернете заявляют, что дублированные ошибки символов должны возникать только в том случае, если в заголовочном файле содержится определение переменной, а ее простое объявление не должно представлять проблему. Причина, по которой мне трудно поверить в это, заключается в том, что я столкнулся с проблемой, хотя мой заголовок содержит только объявление! Я что-то пропустил?

Заранее спасибо за ваше терпение, ребята!

1 ответ

Решение

Заголовочные файлы обычно должны содержать только декларативный код. 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 также. Этот вопрос, кажется, имеет дело с этой проблемой.

Другие вопросы по тегам