C++ 我应该用';如果';声明,冒着性能损失的风险?

C++ 我应该用';如果';声明,冒着性能损失的风险?,c++,c,optimization,cuda,gpgpu,C++,C,Optimization,Cuda,Gpgpu,我有两个非常相似的内核函数,从某种意义上说,代码几乎相同,但略有不同。目前我有两个选择: 写两种不同的方法(但非常相似) 编写单个内核并将不同的代码块放入if/else语句中 if语句会对我的算法性能产生多大影响? 我知道没有分支,因为所有块中的所有线程都将进入if或else 因此,如果内核函数被调用了很多次,那么一个if语句是否会降低性能?您有第三种选择,即使用C++模板,并在IF/Switter语句中使用一个模板参数。实例化您需要的每个版本的内核,然后您就有多个内核在做不同的事情,而无需

我有两个非常相似的内核函数,从某种意义上说,代码几乎相同,但略有不同。目前我有两个选择:

  • 写两种不同的方法(但非常相似)
  • 编写单个内核并将不同的代码块放入if/else语句中
if语句会对我的算法性能产生多大影响?
我知道没有分支,因为所有块中的所有线程都将进入if或else
因此,如果内核函数被调用了很多次,那么一个if语句是否会降低性能?

您有第三种选择,即使用C++模板,并在IF/Switter语句中使用一个模板参数。实例化您需要的每个版本的内核,然后您就有多个内核在做不同的事情,而无需担心分支分歧或条件求值,因为编译器将优化掉死代码和分支

也许是这样的:

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

       case 2:
       // Second code
       break;
    }
}

template void kernel<1>();
template void kernel<2>();
模板
__全局无效内核()
{
开关(动作){
案例1:
//第一代码
打破
案例2:
//第二代码
打破
}
}
模板void kernel();
模板void kernel();

它会略微降低性能,尤其是在内部循环中,因为您经常会浪费一个指令问题槽,但这并不像扭曲是发散的

但是,如果这是一个大问题,那么将条件移出循环是值得的。但是,如果扭曲确实是发散的,请考虑如何删除分支:例如,代替

if (i>0) {
    x = 3;
} else {
    x = y;
}
试一试


x=((i>0)*3)|((我为什么不两个都试试并计时?@talonmes…这个答案是我见过的最有用的答案。我的代码中的CUDA内核数量减少了大约4倍。)模板对于传递线程块大小非常有用。它使块的大小保持静态,同时根据特定的GPU计算能力自适应。(无法以相同的方式使用C中的#define指令。)参见matrixmul.cu示例。变量作为模板参数仍然不起作用,但您可以使用复杂的if语句解决这个问题…
kernel(1,2);
不起作用,但是
if(a==1){kernel(1,2)
}工作。@XapaJIaMnu:据我所知,模板参数只能是类型参数或常量表达式。你说的“变量作为模板参数”是什么意思基本上,我想在模板中使用变量,如果变量是预实例化模板的一部分,并限制该模板只会引发火灾,否则会引发运行时错误。但是,在阅读之后,似乎这是不可能的C++。我希望代码在
a!=1
a!=2
时产生运行时异常。
x = ((i>0)*3) | ((i<3)*y);