как правильно определить функции с помощью шаблонов

0

Мне трудно понять, почему я получаю неразрешенный внешний символ, когда пытаюсь создать программу. У меня 3 файла. Давайте скажем

main.cpp
file.cu
headerfile.h

У меня есть две константные переменные, определенные в моей основной функции в файле main.cpp:

const uint             N = 1048576;
const uint          base = 1024;

Я также определил функции, необходимые в headerfile.h:

template <const uint N, const uint base>
void F1(
    float2 *d_S_x,
    float2 *d_S_y,
    bool *S_yy,
    CCP *dev_CP,
    uint batchSize,
    uint batchLength
);

наряду с другими, такими как:

...
extern "C" uint bitonicSort(
    float2 *d_P_out,
    float2 *d_P_in,
    uint batchSize,
    uint arrayLength,
    uint dir,
    uint xy
);
...

Я должен использовать шаблоны, потому что переменные N и base будут использоваться при распределении разделяемой памяти на устройстве, поэтому мне нужно иметь константные переменные. Функция F1 похожа на функцию интерфейса в file.cu откуда я буду запускать свои ядра. Теперь из main.cpp я обычно вызываю F1

F1 <N,base> ( d_S_x, d_S_y, d_S_yy, dev_CP, batchsize, batchLength);

и я запускаю некоторые ядра из F1 (или другой функции, показанной по ошибке BF), например:

MinReduction <N, base> <<< 1, base >>>(dev_CP);

Что-то не так с определениями функций в файле.h? Я думаю, что я что-то пропускаю с использованием extern вместе с шаблоном? Ошибки:

Error 4 error LNK1120: 2 unresolved externals E:\D....exe
Error 3 error LNK2001: unresolved external symbol "void __cdecl BF<1048576,1024>(struct float2 *,struct CCP *)" (??$BruteForce@$0BAAAAA@$0EAA@@@YAXPAUfloat2@@PAUCCP@@@Z) E:\...main.obj
Error 2 error LNK2001: unresolved external symbol "void __cdecl F1<1048576,1024>(struct float2 *,struct float2 *,bool *,struct CCP *,unsigned int,unsigned int)" (??$closest_pair@$0BAAAAA@$0EAA@@@YAXPAUfloat2@@0PA_NPAUCCP@@II@Z) E:\..main.obj

Где я должен определять функции, если не в headerfile.h? Я понимаю, что Extern сообщает компилятору, что вы не объявляете новую переменную, а ссылаетесь на переменную, объявленную в другом месте. Но определение extern вместе с шаблоном не работает правильно? Любая помощь будет оценена по достоинству. Заранее спасибо.

  • 1
    Любые явные объявления специализации должны быть видны во время создания шаблона. Я подозреваю, что ваши явные / неявные специализации функций шаблона либо видны только в file.cu перевода file.cu но не в основном файле, либо они пропускают объявление шаблона там, где оно выполняется.
  • 1
    Пожалуйста, сократите ваш код до минимально скомпилируемого примера, например: без ваших внешних функций, просто материал шаблона. Также обратите внимание, что вы можете использовать разделяемую память динамически.
Показать ещё 3 комментария
Теги:
templates
cuda

2 ответа

3

Все явные объявления специализации должны быть видны во время создания шаблона.

С вашего (неполного) сообщения кажется, что у вас есть следующий (упрощенный) сценарий:

main.cu file

const int             N = 1048576;
const int          base = 1024;

#include "test.cuh"

int main() {

    F1<N,base>();

    return 0;
}

test.cuh file

template<const int N, const int base> void F1();

test.cu file

template<int N, int base> void F1() { }

Эта структура даст следующее сообщение об ошибке

error LNK2001: unresolved external symbol "void __cdecl F1<1048576,1024>(void)" (??$F1@$0BAAAAA@$0EAA@@@YAXXZ)

Причина в том, что неявная специализация, возникающая в вызове F1<N,base> в файле main.cu не отображается в трансляционной единице, где определен F1 (файл test.cu).

Вы должны использовать что-то вроде

const int             N = 1048576;
const int          base = 1024;

template<int N, int base> void F1() { };

int main() {

    F1<N,base>();

    return 0;
}

В этом случае неявная специализация F1<N,base>(); происходящих в файле main.cu происходит в том же самом main.cu модуле, где F1 определен.

Ваш вопрос не связан с CUDA и является проблемой использования шаблонов в C++. Вы можете ознакомиться с этим руководством для получения более подробной информации.

  • 0
    Спасибо за ответ, но я пытаюсь использовать определения в headerfile.h а не переопределять или объявлять его в файле main.cpp. Я также читаю руководство, которое вы упомянули. :)
-1

Хотя ответ JackOLantern вполне уместен, позвольте быть немного более специфичным для CUDA: интересно, действительно ли вам нужны эти две переменные шаблона.

  • Вы передаете "базу" в качестве размера блока, то есть у вас уже есть какое-то поведение, которое не предполагает его значения. Итак, так важно "заранее знать" его для какой-то части кода?
  • Что касается N, я не знаю, для чего вы его используете, но 1 048 576 = 2 ^ 20 является слишком совершенным числом. Интересно, неужели вы не можете сделать это постоянным? Или передать его ядру в качестве значения перечисления?

Таким образом, вы можете создать проблему для себя... (или вы не можете, но другие в вашей ситуации вполне могут это сделать).

  • 0
    Привет. То, что я пытаюсь сделать, это поместить определение двух интерфейсных функций в headerfile.h . Не беспокойтесь о значениях N и базы. Они не меняются на протяжении всей программы. Я уже определил их как постоянные.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню