对于CUDA,是否可以保证三元运营商可以避免分支差异?

时间:2015-08-14 02:13:11

标签: cuda

我已经阅读了很多关于CUDA分支差异的线索,告诉我使用三元运算符比if / else语句更好,因为三元运算符不会导致分支差异。 我想知道,对于以下代码:

foo = (a > b) ? (bar(a)) : (b);

如果bar是另一个函数或一些更复杂的语句,是否仍然没有分支差异?

1 个答案:

答案 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优化提供更多机会。