3

我发现这篇非常有用的帖子,我想澄清一下关于编译器优化的一些事情。假设我们有这个功能(和原来的帖子一样):

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

       case 2:
       // Second code
       break;
    }
}

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

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

2 回答 2

4

简短的回答:没有。

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

让我想知道为什么您不只是尝试一下并将该代码扔给编译器-它会告诉您模板参数必须是编译时常量。

更新: 由于您在评论中告诉我们它主要不是关于性能,而是关于可读性,我建议使用 switch/case:

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

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

由于您必须在 (ie argv[1][0]) 上做出决定的值仅在运行时才知道,因此您必须使用运行时决定机制。其中,switch/case 是最快的,特别是如果没有太多不同的情况(但超过两个),特别是如果情况之间没有间隙(即'a','b','c',而不是 1、55、2048)。然后编译器可以生成非常快速的跳转表。

于 2013-02-28T15:00:29.853 回答
0

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

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

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

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

于 2013-02-28T16:47:05.887 回答