我有一个模板函数,其中template参数是一个整数。该整数用于创建不同的内核。以前所有可能的模板在表中手工实例化(工作但很难看),但我尝试使用建议的解决方案here。因为我有800多个可能的内核,所以模板递归方法更加优雅。我已经在我的代码的C ++版本上测试了模板递归,它运行得很好,但是nvcc似乎限制了我实例化的递归。
这是我之前丑陋的模板实例化列表的一个简化示例,该列表工作正常(即使使用800内核实例化):
// the template kernel
template <int i> __global__ void kernel(int some_data)
{
switch(i)
{
case 0:
// do something
break;
case 1:
// do some other things
break;
//...
case 799:
// do some other things
break;
}
}
typedef void (*kernel_pointer) (int some_data)
// the ugly huge list
kernel_pointer kernel_list[800] = {
&kernel <0>,
&kernel <1>,
//...
&kernel <799> }
int main()
{
int kernel_index = 10;
//the call
kernel_pointer my_kernel = kernel_list[kernel_index];
my_kernel<<<<1,1>>>>(the_data);
}
这是nvcc不喜欢的漂亮的模板递归。它取代了上一段代码中的列表:
#define N_KERNELS 800
template< int i> bool dispatch_init( kernel_pointer* pTable )
{
pTable[i] = &kernel<i>;
return dispatch_init<i-1>( pTable );
}
// edge case of recursion
template<> bool dispatch_init<-1>(kernel_pointer* pTable) { return true; }
// call the recursive function
const bool initialized = dispatch_init<-1>( kernel_list );
实际上,我没有单一的模板参数,但是它结合起来创建了所有数百种组合。否则,800个案例的开关真的很愚蠢。 有没有人有想法增加nvcc模板递归限制或另一种自动创建列表的方法?
编辑:我发现gcc选项ftemplate-depth更改了实例化递归限制但我还没找到等效的nvcc选项。
答案 0 :(得分:0)
根据Robert Crovella提出的想法,其中包括以几个部分构建表格,这里是一个如何解决&#34;错误的例子。 :
#define N_KERNELS 850
// template kernel
template <int i> __global__ void kernel(int a)
{
switch(i)
{
case 0:
printf("%d\n", a*i);
break;
case 1:
printf("%d\n", a*i);
break;
//...
case 849:
printf("%d\n", a*i);
break;
}
}
typedef void (*kernel_pointer) (int);
kernel_pointer kernel_list[N_KERNELS];
// Function that instantiates all the needed kernels using recursion.
template< int i> bool dispatch_init( kernel_pointer* pTable )
{
pTable[i] = &kernel<i>;
return dispatch_init<i+1>( pTable );
}
// Edge cases of recursion made with a template specialization
template<> bool dispatch_init<199>(kernel_pointer* pTable)
{
pTable[199] = &kernel<199>;
return true;
}
template<> bool dispatch_init<399>(kernel_pointer* pTable)
{
pTable[399] = &kernel<399>;
return true;
}
template<> bool dispatch_init<599>(kernel_pointer* pTable)
{
pTable[599] = &kernel<599>;
return true;
}
template<> bool dispatch_init<799>(kernel_pointer* pTable)
{
pTable[799] = &kernel<799>;
return true;
}
template<> bool dispatch_init<N_KERNELS>(kernel_pointer* pTable) { return true; }
// Call the recursive function few times to instantiate all the kernels without reaching the recursive instantiation limit
const bool initialized = dispatch_init<0 >( kernel_list );
const bool initialized = dispatch_init<200>( kernel_list );
const bool initialized = dispatch_init<400>( kernel_list );
const bool initialized = dispatch_init<600>( kernel_list );
const bool initialized = dispatch_init<800>( kernel_list );
int main()
{
int kernel_index = 10;
kernel_pointer my_kernel = kernel_list[kernel_index];
my_kernel<<<<1,1>>>>(6);
}
我不喜欢这个修复,但它暂时会解决这个问题。 如果Nvidia开发人员有一天来到这里,那么添加选项&#34; ftemplate-depth&#34;应该是个好主意。到nvcc,没有?