为什么流水线工作对于(a + b)+(c + d)比对+ b + c + d更好?

时间:2013-11-25 21:48:54

标签: c optimization assembly pipeline

this answer有人写道

  

[..]大多数编译器不会优化a + b + c + d到(a + b)+(c + d)(这是一个优化,因为第二个表达式可以更好地流水线化)

最初的问题是由于浮点运算的不精确性,某些涉及float值的表达式如何能够或不能被重新排序。

我对上面的部分更感兴趣:为什么 - 例如,使用unsigned int值 - 如果将a+b+c+d重写为(a+b)+(c+d),生成利用CPU管道的代码会更容易吗? }?

3 个答案:

答案 0 :(得分:3)

a + b和c + d可以并行计算。

像这样:

x = a+b
y = c+d
return x+y // requires x and y

VS

x = a+b
y = x+c // requires x
return y+d // requires y (and thus x)

在计算y时,必须先等待x的结果,但它们之间存在数据依赖关系。请参阅维基百科上的Instruction-level parallelism

答案 1 :(得分:2)

使用unsigned int?它不会。 整数操作可以自由地重新排序,而不会有任何影响结果的风险,因此任何半合适的编译器都应该为两个表达式生成相同的代码,因为它们在讨论浮点数时只是意味着不同的东西。

答案 2 :(得分:2)

如果编译器生成中间SSA,它可能看起来像:

AB = a + b;
ABC = AB + c;
ABCD = ABC + d;

在第一种情况下,并且:

AB = a + b;
CD = c + d;
ABCD = AB + CD;

在案例1中,每个术语都包含前一个术语,因此即使ALU能够一次添加多个术语,它也必须等待上一个操作的结果才能开始下一个术语。在第二种情况下,像具有多个ALU流水线的现代x86这样的处理器可以独立地同时计算ABCD