如果在C ++中,无分支将是什么样子?

| 我意识到我在该领域非常缺乏知识(以一种怪异的方式说我不知道​​杰克)。 是否有关于如何以及何时使用它们的文档?     
已邀请:
除了所有基于纠结的无分支代码(不会覆盖所有内容,例如FP)之外,您还获得了专门用于创建无分支代码的指令,它们在x86下分别是
SETcc
FCMOVcc
CMOVcc
,它们根据条件执行操作。比较中的标志。 一个非常简单的例子是(是的,这个例子是如此简单,以至于永远都不会写这样的东西,只是为了清楚地说明这一点):
bool CheckZero(int x)
{
    if(x == 0)
       return true;

    return false;
    //OR we can use: return (x == 0) ? true : false; 
}
现在,一个简单的x86编译器可能会将其编译为:
    MOV EAX,[ESP + 4]
    TEXT EAX,EAX
    JE _TRUE
    XOR EAX,EAX
    RETN 4

_TRUE:
    MOV EAX,1
    RETN 4
优化的x86编译器会将其分解为以下无分支代码(或类似代码):
MOV ECX,[ESP + 4]
XOR EAX,EAX
TEST ECX,ECX
SETE AL
RETN 4
在这里可以找到更复杂的示例。 但是,这是编译器将要执行的事情,您不必担心自己(至少在不分析编译器输出的情况下)。但是,如果要求代码必须无分支无误,则C ++不能提供足够的控制来做到这一点,因此您需要使用(内联)汇编。     
http://hbfs.wordpress.com/2008/08/05/branchless-equivalents-of-simple-functions/ 我认为(尽管我不了解我在页面上所读的内容),但是这是一种获取是否不分支功能的方法(基于无分支if的说法是有意义的)。不知道更多。 感谢Google先生。     
我不久前写了三元逻辑模拟器,这个问题对我来说是可行的,因为它直接影响我的解释器的执行速度。我被要求尽可能快地模拟大量的三元逻辑门。 在二进制编码的三进制系统中,一个三位组合成两位。最高有效位表示负,最低有效位表示正。情况“ 11”不应发生,但必须正确处理并以0表示威胁。 考虑一下“ 6”函数,该函数应将格式化后的trit返回为正整数-1、0或1;正如我观察到的,有4种方法:我称它们为\“ cond \”,\“ mod \”,\“ math \”和\“ lut \”;让我们调查一下 首先基于jz | jnz和jl | jb条件跳转,因此确定。它的性能根本不好,因为它依赖于分支预测器。甚至更糟的是-它会有所不同,因为未知是否会有一个或两个先验分支。这是一个示例:
inline int bct_decoder_cond( unsigned bctData ) {
   unsigned lsB = bctData & 1;
   unsigned msB = bctData >> 1;
   return
       ( lsB == msB ) ? 0 : // most possible -> make zero fastest branch
       ( lsB > msB ) ? 1 : -1;
}
这是最慢的版本,在最坏的情况下它可能涉及2个分支,这是二进制逻辑失败的地方。在我的3770k上,它对随机数据的平均处理能力约为200MIPS。 (这里和之后-每个测试是随机填充2mb数据集的1000次尝试的平均值) 下一个依赖于模运算符,其速度介于第一和第三之间,但绝对更快-600 MIPS:
inline int bct_decoder_mod( unsigned bctData ) {
    return ( int )( ( bctData + 1 ) % 3 ) - 1;
}
下一个是无分支方法,它仅涉及数学,因此仅涉及数学。它根本不假设跳转指令:
inline int bct_decoder_math( unsigned bctData ) {
    return ( int )( bctData & 1 ) - ( int )( bctData >> 1 );
}
这确实应该做的,并且表现得非常好。相比之下,性能估计为1000 MIPS,比分支版本快5倍。由于缺少本地2位带符号的int支持,因此分支版本的速度可能有所降低。但是在我的应用程序中,它本身就是一个很好的版本。 如果这还不够,那么我们可以做一些特别的事情。接下来称为查找表方法:
inline int bct_decoder_lut( unsigned bctData ) {
    static const int decoderLUT[] = { 0, 1, -1, 0 };
    return decoderLUT[ bctData & 0x3 ];
}
在我的情况下,一个三位一体仅占用了2位,因此lut表只有2b * 4 = 8个字节,值得尝试。它适合高速缓存,工作速度高达1400-1600 MIPS,这是我的测量精度下降的地方。这是快速数学方法的1.5倍加速。那是因为您只有预先计算的结果和单个“ 11”指令。不幸的是,缓存很小,并且(如果索引长度大于几位)您将无法使用它。 所以我想我回答了您的问题,关于分支/无分支代码是什么样的。答案要好得多,并提供详细的示例,实际应用和实际性能测量结果。     

要回复问题请先登录注册