如何使用模板正确定义函数

时间:2013-11-26 14:52:01

标签: c++ c templates cuda

当我尝试构建程序时,我无法理解为什么会得到未解析的外部符号。我有3个文件。让我们说

main.cpp
file.cu
headerfile.h

我在main.cpp文件的主函数中定义了这两个const变量:

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
);
...

我必须使用模板,因为变量Nbase将用于在设备上分配共享内存,所以我需要有const变量。 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和模板不起作用吗? 任何帮助,将不胜感激。提前谢谢。

2 个答案:

答案 0 :(得分: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出现在定义F1的同一个转换单元中。

您的问题与CUDA无关,是在C ++中使用模板的问题。您可以查看此guide以获取更直接的信息。

答案 1 :(得分:-1)

虽然JackOLantern's answer非常重要,但让我们更具体的CUDA:我想知道你是否真的需要这两个模板变量。

  • 您将'base'作为块大小传递,这意味着您已经有一些不承担其值的行为。那么,对于代码的某些部分提前“知道”它是否如此重要?
  • 至于N,我不知道你用它是什么,但1,048,576 = 2 ^ 20有点太完美了。我想知道 - 你不能让它成为常数吗?或者将其作为枚举值传递给内核?

所以,你可能会为自己创造问题......(或者你可能没有,但在你的情况下其他人可能会这样做。)