C++ CUDA和模板:需要专门化声明吗?

C++ CUDA和模板:需要专门化声明吗?,c++,cuda,C++,Cuda,我有一个模板包装函数,它调用.cu文件中定义的内核(\uuuu global\uuuu) template<typename T, class M> __global__ void compute_kernel(T* input, T* output, n) { M m; // compute stuff using m }; template<typename T, class M> void compute(T* input, T* output

我有一个模板包装函数,它调用.cu文件中定义的内核(
\uuuu global\uuuu

template<typename T, class M> 
__global__ void compute_kernel(T* input, T* output, n) {
    M m;
    // compute stuff using m
};

template<typename T, class M> 
void compute(T* input, T* output, int n) {
    // ... compute blocks, threads, etc.
    compute_kernel<T,M> <<<dim_grid, dim_block>>>(input, output, n);
    // ...
};
那么,是否有必要专门化每个模板化函数以使其能够从主机调用?(这是一个很大的缺点)

谢谢你的评论

这是一个,不限于CUDA

如果您在.cpp或.cu文件中有一个模板实现,那么当您编译该翻译单元时,编译器可能无法知道您将需要什么样的模板参数排列。因此,当你链接你会得到错误


您可以将实现放在头文件中(在这种情况下,您需要在.cu文件中实例化,因为它包含CUDA),或者必须显式实例化所有必需的排列。如果您必须执行这些操作,那么您可以使用宏来实例化所有排列。

与任何模板一样,您必须确保在每个实例化站点上都可以看到整个模板定义(除非您有意提供显式实例化)。@KerrekSB:我想您是对的,这就是问题所在。然而,要分离主机和设备代码(以及编译),似乎不可能使整个模板定义随处可见……我不确定问题出在哪里。CUDA编译器不是自动将两个代码路径分开吗?因此,只需使用函数模板的模板定义创建一个普通头文件,并将其包含在所有地方-有什么阻碍?如果我没有正确理解,请原谅。当然,可以在任何地方包含
compute()
的定义,因为这只是主机代码。但是
compute\u kernel()
也是模板化的,不可能在任何地方都包含它的定义,
g++
抱怨(主要是关于内核调用中的定义)。因此,我最终得到了
compute\u kernel()
的专门化,它根本不会改变任何东西。为什么不使用
nvcc
编译所有东西呢?这将为您调用适当的“真实”编译器,并将主机和设备代码分开。谢谢,这就解决了这个问题。我从来没有真正考虑过模板的非内联实现,并且总是将它们保存在头文件中。因此,只要我只从*.cu文件中调用模板函数,我就可以在任何地方包含完整的定义,而不需要显式实例化。这已经是一个很大的帮助,因为(最终)只有我的单元测试将从宿主代码调用这些函数。@Tom在CUDA中使用表达式模板怎么样?我在这里贴了一个问题,但没有得到回答。对于表达式模板,似乎不可能实例化所有可能的排列。你能提出一个解决方案吗?@Jackolanten这不是同样的问题吗?如果显式地实例化所有排列是不切实际的,那么应该将实现放在头文件中,以便在需要时可以使用它。在这方面,C++没有什么不同。“Tom Yes,你说得对。J.M. Cohen,“用C++元编程处理设备阵列”,GPU计算GEMS -翡翠版最近澄清了我的全貌。在C++和CUDA中,表达式模板没有差异。对于前者,操作由经典函数调用执行,而对于后者,操作由
内核启动执行。非常感谢。
template<typename T, class M> 
void compute(T* input, T* output, int n);
template void
compute<int, Method1<int> >(int* input, int* output, int n);

template void
compute<float, Method1<float> >(float* input, float* output, int n);

template void
compute<int, Method2<int> >(int* input, int* output, int n);

template void
compute<float, Method2<float> >(float* input, float* output, int n);