C++ CUDA C++;核参数的模板化

C++ CUDA C++;核参数的模板化,c++,templates,cuda,C++,Templates,Cuda,我试图基于布尔变量(如图所示:)对CUDA内核进行模板化,但我不断收到一个编译器错误,它说我的函数不是模板。我想我只是错过了一些明显的东西,所以这很令人沮丧 以下操作不起作用: util.cuh #include "kernels.cuh" //Utility functions #include "kernels.cuh" //Utility functions 麦粒 #ifndef KERNELS #define KERNELS template<bool

我试图基于布尔变量(如图所示:)对CUDA内核进行模板化,但我不断收到一个编译器错误,它说我的函数不是模板。我想我只是错过了一些明显的东西,所以这很令人沮丧

以下操作不起作用:

util.cuh

#include "kernels.cuh"
//Utility functions
#include "kernels.cuh"
//Utility functions
麦粒

    #ifndef KERNELS
    #define KERNELS
    template<bool approx>
    __global__ void kernel(...params...);
    #endif
#ifndef KERNELS
#define KERNELS
template<bool approx>
__global__ void kernel(...params...);
template<bool approx>
__global__ void kernel(...params...)
{
    if(approx)
    {
       //Approximate calculation
    }
    else
    {
      //Exact calculation
    }
}
#endif
麦粒

    #ifndef KERNELS
    #define KERNELS
    template<bool approx>
    __global__ void kernel(...params...);
    #endif
#ifndef KERNELS
#define KERNELS
template<bool approx>
__global__ void kernel(...params...);
template<bool approx>
__global__ void kernel(...params...)
{
    if(approx)
    {
       //Approximate calculation
    }
    else
    {
      //Exact calculation
    }
}
#endif
如果有什么不同,我会在一行中编译所有的.cu文件,如:

nvcc -O3 -arch=sm_21 -I. main.cu kernels.cu -o program

所有显式专门化声明必须在模板实例化时可见。您的显式专门化声明仅在kernels.cu翻译单元中可见,而在main.cu中不可见

下面的代码确实工作正常(除了在显式实例化指令中添加一个
\uuuu全局\uuuu
限定符)

#包括
#包括
#包括
#包括
模板
__全局无效内核()
{
如果(大约)
{
printf(“真实分支机构”);
}
其他的
{
printf(“假分支”);
}
}
模板_u全局_uu无效内核();
内部主(空){
内核();
getch();
返回0;
}
编辑

<>在C++中,模板函数不会被编译,直到遇到函数的显式实例化。从这个角度来看,现在完全支持模板的CUDA的行为与C++ +/P>完全相同。 举个具体的例子,当编译器发现

template<class T>
__global__ void kernel(...params...)
{
    ...
    T a;
    ...
}
模板
__全局无效内核(…参数…)
{
...
Tα;
...
}
它只检查函数语法,但不生成目标代码。因此,如果您像上面那样使用单个模板函数编译一个文件,那么您将拥有一个“空”对象文件。这是合理的,因为编译器不知道将哪个类型分配给
a

编译器仅在遇到函数模板的显式实例化时才生成目标代码。此时,模板函数的编译就是这样工作的,这种行为为多个文件项目引入了限制:模板函数的实现(定义)必须与其声明位于同一个文件中。因此,您不能将
kernels.cuh
中包含的接口与
kernels.cu
分开,这是代码的第一个版本无法编译的主要原因。因此,必须在使用模板的任何文件中同时包含接口和实现,即,必须在
main.cu
中同时包含接口和实现、
kernels.cuh
kernels.cu

由于没有显式实例化就不会生成代码,因此编译器允许在项目中多次包含同一模板文件,同时包含声明和定义,而不会生成链接错误


<>在C++中使用模板有几个教程。除了令人恼火的标题外,我将为您提供一个关于该主题的分步介绍。

虽然添加了
\uuuu global\uuuu
并没有解决我的问题,但这样做并将我的整个函数声明放入
内核。cuh
解决了。我宁愿将其保存在
内核中。cu
但是-这可能吗?@Adam27X我已经尝试在我编辑的答案中解释为什么您的第一个版本的代码不起作用。为了完整性,您可以替换
getch()用于
cudadeviceset()取而代之。在这种情况下,添加
#包括

kernel is not a template
invalid explicit instantiation declaration
nvcc -O3 -arch=sm_21 -I. main.cu kernels.cu -o program
#include<cuda.h>
#include<cuda_runtime.h>
#include<stdio.h>
#include<conio.h>

template<bool approx>
__global__ void kernel()
{
    if(approx)
    {
        printf("True branch\n");
    }
    else
    {
        printf("False branch\n");
    }
}

template __global__ void kernel<false>();

int main(void) {
    kernel<false><<<1,1>>>();
    getch();
    return 0;
}
template<class T>
__global__ void kernel(...params...)
{
    ...
    T a;
    ...
}