我已经阅读了很多关于CUDA分支差异的线索,告诉我使用三元运算符比if / else语句更好,因为三元运算符不会导致分支差异。 我想知道,对于以下代码:
foo = (a > b) ? (bar(a)) : (b);
如果bar是另一个函数或一些更复杂的语句,是否仍然没有分支差异?
答案 0 :(得分:5)
(我想添加@njuffa答案的评论,但我的声誉还不够) 我发现它们与我的程序有不同的表现。 if子句样式花费4.78ms:
// fin is {0-4}, range_limit = 5
if(fin >= range_limit){
res_set = res_set^1;
fx_ref = fx + (fxw*(float)DEPTH_M_H/(float)DEPTH_BLOCK_X);
fin = 0;
}
// then branch for next loop iteration.
// nvvp report these assemblies.
@!P1 LOP32I.XOR R48, R48, 0x1;
@!P1 FMUL.FTZ R39, R7, 14;
@!P1 MOV R0, RZ;
MOV R40, R48;
{ @!P1 FFMA.FTZ R6, R39, c[0x2][0x0], R5;
@!P0 BRA `(.L_35); } // the predicate also use for loop's branching
三元风格的成本为4.46毫秒:
res_set = (fin < range_limit) ? res_set: (res_set ^1);
fx_ref = (fin < range_limit) ? fx_ref : fx + (fxw*(float)DEPTH_M_H/(float)DEPTH_BLOCK_X) ;
fin = (fin < range_limit) ? fin:0;
//comments are where nvvp mark the instructions are for the particular code line
ISETP.GE.AND P2, PT, R34.reuse, c[0x0][0x160], PT; //res_set
FADD.FTZ R27, -R25, R4;
ISETP.LT.AND P0, PT, R34, c[0x0][0x160], PT; //fx_ref
IADD32I R10, R10, 0x1;
SHL R0, R9, 0x2;
SEL R4, R4, R27, P1;
ISETP.LT.AND P1, PT, R10, 0x5, PT;
IADD R33, R0, R26;
{ SEL R0, RZ, 0x1, !P2;
STS [R33], R58; }
{ FADD.FTZ R3, R3, 74.75;
STS [R33+0x8], R29; }
{ @!P0 FMUL.FTZ R28, R4, 14; //fx_ref
STS [R33+0x10], R30; }
{ IADD32I R24, R24, 0x1;
STS [R33+0x18], R31; }
{ LOP.XOR R9, R0, R9; //res_set
STS [R33+0x20], R32; }
{ SEL R0, R34, RZ, P0; //fin
STS [R33+0x28], R36; }
{ @!P0 FFMA.FTZ R2, R28, c[0x2][0x0], R3; //fx_ref
插入的行来自下一个循环迭代计算。 我认为在许多指令共享相同谓词值的情况下,三元样式可能为ILP优化提供更多机会。