长行整数运算

时间:2010-10-26 05:39:22

标签: c++

两部分我的问题。哪个更有效/更快:

int a,b,c,d,e,f;
int a1,b1,c1,d1,e1,f1;
int SumValue=0; // oops forgot zero
// ... define all values
SumValue=a*a1+b*b1+c*c1+d*d1+e*e1*f*f1;

Sumvalue+=a*a1+b*b1+c*c1;
Sumvalue+=d*d1+e*e1*f*f1;

我猜第一个是。我的第二个问题是为什么。

我想第三个问题是,在任何时候都需要分解一个加法运算(除了编译器对行连续数等的限制......)。

修改

当整个算术运算无法适应缓存时,我是唯一一次看到减速的时间吗?我认为这是不可能的 - 在这种情况发生之前,编译器可能会因为两次线路延续而感到生气。也许我明天要玩,看看。

4 个答案:

答案 0 :(得分:5)

你有没有衡量?两种方法的优化机器代码可能非常相似,如果不相同的话。

编辑:我刚试过这个,结果就是我的预期:

$ gcc -O2 -S math1.c  # your first approach
$ gcc -O2 -S math2.c  # your second approach
$ diff -u math1.s math2.s

--- math1.s 2010-10-26 19:35:06.487021094 +0200
+++ math2.s 2010-10-26 19:35:08.918020954 +0200
@@ -1,4 +1,4 @@
-   .file   "math1.c"
+   .file   "math2.c"
    .section    .rodata.str1.1,"aMS",@progbits,1
 .LC0:
    .string "%d\n"

就是这样。相同的机器代码。

答案 1 :(得分:2)

你可以在一行上组合的操作数没有任意限制......实际上,编译器会接受你想要抛出的任何数字。编译器对操作的考虑发生在规定换行之后很久 - 它处理词法符号和语法规则,然后是抽象语法树。除非您的编译器编写得非常糟糕,否则这两个语句对int数据的执行效果都相同。

请注意,在result = a * b + c * d + e * f等中,编译器没有序列点并且知道优先级,因此可以完全自由地并行地评估和组合子表达式(给定有能力的硬件)。结果+ = a * b;结果+ = c * d;方法,你插入序列点,所以要求编译器在另一个之前完成一个表达式,但是可以自由地 - 并且应该 - 意识到结果不会在增量之间的其他地方使用,因此它可以像第一种情况一样自由优化

更一般地说:我可以为这些性能查询提供的最佳建议是1)不要担心它是一个实际问题,除非你的程序运行得太慢,然后分析找出哪里2)如果好奇或分析表明问题,然后尝试你能想到的两种/所有方法并测量实际表现。

除此之外:+ =有时可能更有效,例如:连接到现有字符串,因为这些对象上的+可能涉及创建临时和更多的内存分配 - 模板表达式解决这个问题但很少使用,因为它们实现起来非常复杂并且编译速度较慢。

答案 2 :(得分:1)

这就是熟悉汇编语言的原因。在这两种情况下,将生成汇编指令,将操作数对​​加载到寄存器中并执行加法/乘法,并将结果存储在寄存器中。根据您使用SumValue

的方式,也可能会生成将最终结果存储在SumValue.所代表的内存地址中的说明

简而言之,两种结构都可能执行相同的操作,尤其是对于优化标记。即使他们在某个平台上执行相同的操作,这两种方法都没有任何内在因素可以帮助解释为什么在C ++级别。通过查看编译器如何将C ++构造转换为汇编指令,您最多能够理解为什么一个表现优于另一个的原因。

  

我想第三个问题就是   点是否有必要打破   增加操作(除此之外)   编译器对行数的限制   延续等......)。

分解添加操作并不是必要。但它可能有助于提高可读性。

答案 3 :(得分:0)

它们最有可能被转换为相同数量的机器指令,因此它们需要相同的时间。