模板参数作为函数说明符和编译器优化

时间:2013-02-28 14:54:54

标签: c++ cuda nvcc

我发现this非常有用的帖子,我想澄清一下有关编译器优化的内容。让我们说我们有这个功能(与原帖相同):

template<int action>
__global__ void kernel()
{
    switch(action) {
       case 1:
       // First code
       break;

       case 2:
       // Second code
       break;
    }
}

编译器是否会在消除无法访问的代码的意义上进行优化,即使我在编译时调用了模板变量未知的函数 - 比如创建两个separete函数? E.g:

kernel<argv[1][0]>();

2 个答案:

答案 0 :(得分:4)

简答:不。

模板是在编译时实例化和生成的,所以你不能使用argv中的值,因为它们在编译时是不可知的。

让我想知道你为什么不试一试并将代码扔到编译器上 - 它会告诉你模板参数必须是编译时常量。

<强>更新 由于您在评论中告诉我们它不是主要关于性能,而是关于可读性,我建议使用开关/案例:

template <char c> void kernel() {
  //...
  switch(c) { /* ... */ }
}

switch (argv[1][0]) {
  case 'a': 
    kernel<'a'>();
    break;
  case 'b': 
    kernel<'b'>();
    break;
  //...
}

由于您必须进行决策的值(即argv[1][0])仅在运行时已知,因此您必须使用运行时决策机制。其中,开关/外壳是最快的,特别是如果没有太多不同的情况(但超过两个),特别是如果情况之间没有间隙(即&#39; a&#39;,&#39; ; b&#39;,&#39; c&#39;,而不是1,55,2048)。然后编译器可以生成非常快的跳转表。

答案 1 :(得分:0)

对模板不熟悉我不得不研究一些基本问题。最后,我想出了解决问题的方法。如果我想根据命令行参数调用带有模板参数的函数,我应该这样做:

if(argv[1][0] == '1')
    kernel<1><<< ... >>>();

if(argv[1][0] == '2')
    kernel<2><<< ... >>>();

我还检查了这样的程序的ptx文件,发现编译器在这种情况下优化生成两个不同的内核函数而没有switch语句。