CUDA c++:使用调用模板内核的模板函数

CUDA C++: Using a template function which calls a template kernel

本文关键字:内核 函数 调用 c++ CUDA      更新时间:2023-10-16

我有一个类,它有一个模板函数。这个函数调用模板内核。我在Linux机器上使用insight进行开发。在这样做的过程中,我遇到了以下两个相互冲突的需求:

1 -当实现模板函数时,定义必须出现在*.h(或*.cu.h)文件中,因为直到需要模板时才生成代码。

2 -内核代码必须出现在*。Cu,因为编译器无法识别<<<和>>>令牌,当它们在头文件中时。

我认为可能有一种方法可以绕过第二个问题,使用一些编译器巫术。

当我在*.cu.h文件中设置模板成员函数所在的系统时,我得到以下编译器错误:

错误:'<'标记前期望的主表达式

错误:'>'标记前预期的主表达式

这似乎表明它正在解析<<然后是>>符号不识别<<<或>>>令牌

代码相关部分的总体结构大纲如下:

在MyClass.cu.h:

#include "MyKernels.cu.h"
class MyClass{
    template <typename T> void myFunction(T* param1, int param2);
};
template <typename T> void myFunction(T* param1, int param2){
    blocks = 16;
    blockSize = 512;
    myKernel<<<blocks, bockSize>>>(d_param1, param2);
}
在MyKernels.cu.h:

#ifndef MYKERNELS_H_
#define MYKERNELS_H_
template <typename T>
extern __global__ void myKernel(T* param1, int param2);
#endif
在MyKernels.cu:

#include "MyKernels.cu.h"
template<typename T>
__global__ void myKernel(T* param1, int param2){
    //Do stuff
}

编辑7/31/2015:为了使我试图完成的结构更清楚一些,我写了一个小的示范项目。它在github上公开发布在以下URL:

https://github.com/nvparrish/CudaTemplateProblem

包装器函数声明需要在头文件中。函数定义没有。

我是这么想的:

$ cat MyClass.cuh
template <typename T> void kernel_wrapper(T*, int);
class MyClass{
  public:
    template <typename T> void myFunction(T* param1, int param2);
};
template <typename T> void MyClass::myFunction(T* param1, int param2){
    kernel_wrapper(param1, param2);
}
$ cat MyKernels.cu
#include "MyClass.cuh"
#define nTPB 256
template <typename T>
__global__ void myKernel(T* param1, int param2){
  int i = threadIdx.x+blockDim.x*blockIdx.x;
  if (i < param2){
    param1[i] += (T)param2;
  }
}
template <typename T>
void kernel_wrapper(T* param1, int param2){
  myKernel<<<(param2+nTPB-1)/nTPB,nTPB>>>(param1, param2);
  cudaDeviceSynchronize();
}
template void MyClass::myFunction(float *, int);
template void MyClass::myFunction(int *, int);
$ cat mymain.cpp
#include "MyClass.cuh"
int main(){
  MyClass A;
  float *fdata;
  int *idata, size;
  A.myFunction(fdata, size);
  A.myFunction(idata, size);
}
$ nvcc -c MyKernels.cu
$ g++ -o test mymain.cpp MyKernels.o -L/usr/local/cuda/lib64 -lcudart
$

注意强制模板实例化。如果您希望模板专门化发生在一个编译单元(.cu文件,内核定义所属的地方)中,这将是必要的,因此它可以在另一个编译单元(.cpp文件,不理解cuda语法)中使用。