逐块优化循环

时间:2011-07-20 01:45:57

标签: c

在下面的代码中,有没有办法避免使用if语句?

s = 13;   /*Total size*/
b = 5;    /*Block size*/
x = 0;
b1 = b;
while(x < s)
{
    if(x + b > s)
        b1 = s-x;
    SendData(x, b1);   /*SendData(offset,length);*/
    x += b1;
}

非常感谢!

4 个答案:

答案 0 :(得分:2)

我不知道也许你会想:

s = 13;   /*Total size*/
b = 5;    /*Block size*/
x = 0;
while(x + b < s)
{
    SendData(x, b);   /*SendData(offset,length);*/
    x += b;
}
SendData(x, s%b);

更好吗?

答案 1 :(得分:1)

不要把时间浪费在你的编译器可能为你做的毫无意义的微优化上。

程序员的程序;不是电脑。编译器变得越来越好,但程序员却没有。

如果它使你的程序更具可读性(@PaulPRO的答案),那就去做吧。否则,不要。

答案 2 :(得分:0)

如果您尝试删除if(),则可能会更改您的逻辑,您必须花费大量时间进行测试。我只看到一个潜在的变化:

s = 13;
b = 5;
x = 0;
b1 = b;
while(x < s)
{
  const unsigned int total = x + b;  // <--- introduce 'total' 
  if(total > s)
    b1 = s-x;
  SendData(x, b1);
  x = total;   // <--- reusing it
}

答案 3 :(得分:0)

您可以使用conditional movebranchless integer select分配b1而不使用if语句:

// if a >= 0, return x, else y
// assumes 32-bit processors
inline int isel( int a, int x, int y ) // inlining is important here
{
    int mask = a >> 31; // arithmetic shift right, splat out the sign bit
    // mask is 0xFFFFFFFF if (a < 0) and 0x00 otherwise.
    return x + ((y - x) & mask);
};

// ...
while(x < s)
{
    b1 = isel( x + b - s, s-x, b1 );
    SendData(x, b1);   /*SendData(offset,length);*/
    x += b1;
}

但这只是对有序处理器的有用优化。它在现代PC的x86上没有任何区别,它具有快速分支和重新排序单元。它可能在某些嵌入式系统(如Playstation)上很有用,其中pipeline latency对于性能而言比指令计数更重要。我用它在紧密的循环中剃了几微秒。

理论上,编译器“应该”能够将三元表达式(b = (a > 0 ? x : y))转换为条件移动,但我从来没有遇到过这样做过。

当然,从更广泛的意义上说,与SendData()的成本相比,每个人都认为这是无意义的优化是正确的。 cmov和分支之间的差异大约是4纳秒,与网络呼叫的成本相比可以忽略不计。花费你的时间修复这个分支,每次网络呼叫发生一次,就像开车穿越城镇,以节省汽油1美分。