我有一个具有模板功能的类。该函数调用模板内核。我在Linux机器上用Nsight进行开发。在这样做时,我遇到了以下一对冲突的要求:
1 - 实现模板函数时,定义必须出现在* .h(或* .cu.h)文件中,因为在需要模板之前不会生成代码。
2 - 内核代码必须出现在* .cu中,因为编译器无法识别<<<和>>>标记文件中的标记。
我认为可能有一种方法可以通过一个小的编译器巫术来解决第二个问题。
当我设置模板成员函数在* .cu.h文件中的系统时,我得到以下编译器错误:
错误:在'<'之前预期的primary-expression令牌
错误:在'>'之前预期的主要表达令牌
这似乎表明它正在解析<<然后>>令牌并且不识别<<<或>>>令牌。
代码相关部分的结构概要如下:
在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
}
编辑2015年7月31日: 为了使我想要完成的结构更加清晰,我写了一个小的示范项目。它在github上公开发布在以下网址:
答案 0 :(得分:1)
包装函数声明需要在头文件中。函数定义没有。
以下是我的想法:
$ 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语法)。