模板过度递归在实例化cuda

时间:2014-09-08 08:15:09

标签: templates recursion cuda nvcc

我有一个模板函数,其中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选项。

1 个答案:

答案 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,没有?