我发现this非常有用的帖子,我想澄清一些关于编译器优化的事情。假设我们有这个函数(和最初的post一样):
template<int action>
__global__ void kernel()
{
switch(action) {
case 1:
// First code
break;
case 2:
// Second code
break;
}
}
即使我在编译时使用未知的模板变量调用函数,编译器是否会进行某种意义上的优化,以消除无法访问的代码-类似于创建两个单独的函数?例如:
kernel<argv[1][0]>();
发布于 2013-02-28 15:00:30
简短的回答是:不。
模板完全是在编译时实例化和生成的,所以不能使用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]
)仅在运行时才知道,因此您必须使用运行时判断机制。其中,switch/case是最快的,特别是如果不是有太多不同的case(但超过两个),特别是如果case之间没有间隙(即'a','b','c',而不是1,55,2048)。然后,编译器可以生成非常快的跳转表。
发布于 2013-02-28 16:47:06
作为模板的新手,我不得不研究一些基本的问题。最后,我想出了我的问题的解决方案。如果我想调用依赖于命令行参数的带有模板参数的函数,我应该这样做:
if(argv[1][0] == '1')
kernel<1><<< ... >>>();
if(argv[1][0] == '2')
kernel<2><<< ... >>>();
我还检查了这类程序的ptx文件,发现编译器在这种情况下进行了优化,在没有switch
语句的情况下产生了两个不同的内核函数。
https://stackoverflow.com/questions/15138583
复制