Double multiplication vs addition speed
背景
我是一名航空航天工程和欧洲经济共同体的学生。我现在正在学习大量的数学和物理知识,但还没有开始学习算法或汇编语言。
我设计和编写了各种各样的程序,从商业提案软件到卫星硬件控制器。
这项工作的大部分涉及到在其他媒介中做数学,然后编写代码来实现它。
在将这些方程编码之前,我用代数方法简化了它们。但在我花时间做这件事之前,我想知道我是应该支持更多的加法运算,还是更多的乘法运算。(我已经知道分工要贵得多。)
例子
。
这是我从其他作品中推导出来的一个方程,这是我所看到的非常典型的方程。
我们可以清楚地看到,至少有几种方法可以简化这个方程。由于简化是我的自由裁量权,我想选择的选择,有利于性能尽可能实际。我不会以算法设计时间为代价来追求边缘性能。
问题
一般来说,哪种双运算更快:加法还是乘法?
我知道唯一确定的方法是写和运行基准,但这不是重点。在我每次需要简化一个方程式时,这并不是一个足够高的优先级来证明编写测试代码的合理性。我需要一条经验法则来应用于我的代数。
如果差异如此之小以至于接近于可忽略或不确定,那是一个可以接受的答案,只要我知道它几乎没有什么区别。
支持研究
我知道,在C和C++中,优化器处理代数,所以这是一个空问题。但是,据我所知,Java编译器不执行代数简化/优化。具体来说,这个答案表明情况是这样的,程序员应该做这种优化。
互联网上对此的答案是零散的,但我无法得出结论性的答案。一位马里兰大学的前物理系学生在Java上进行了这些测试,但是表中没有双性能数据,图形比例使结果难以识别。这个魁北克大学教授的测试只显示整数运算的结果。这个答案解释了,在硬件层面上,乘法运算是一个更复杂的运算,但我也知道工程师们在设计处理器时考虑到了这些事情。
其他稍微有用的链接:
百万千克1所以:十进制和双速百万千克1百万千克1IBM关于Java字节码的文章百万千克1百万千克1SO:理论加法运算与乘法运算百万千克1百万千克1那么:(n-乘法)与(n/2-乘法+2加法)哪个更好?百万千克1
型
- 型编译器不会;运行时会进行优化。(坦率地说,如果没有足够高的优先级来为其编写基准,那么就没有足够高的优先级来关心这两种情况。)这意味着:添加通常会更快。
- 型@路易斯瓦瑟曼"没有足够的优先权来关心任何一种方式。"我同意这一点,但如果我无论如何都需要解方程,我想这样做的方式可能会产生更好的结果。如果我有两条上下班的路线,它们需要同样的时间和燃料,但其中一条不太可能发生事故,我会选择这条路线,即使大多数时间没有差别。
- 型如果您关心差异,而且还没有人做过比较,那么就运行一些基准来进行比较。如果花几个小时来做这件事还不够重要,那就根本不重要了。或者你希望我们为你做这项工作?
- 型你应该更关注每一项的数量级,而不是你是否可以最小化被乘数的数量,并以最小化溢出/下溢可能性的方式对操作进行分组,也就是说,在你的例子中,实际上只有一个重构可能有用:有两个项乘以(c-1)X。
- 型我的经验法则是使代码尽可能可读,因为正确比快速更重要。在任何语言中,我很少遇到这样的情况:为了达到性能目标,我必须扭曲代数表达式。我的建议是用你最舒服的方式来写这个表达,一年后你就可以轻松地阅读了。如果到了你需要担心性能的时候,那么你应该进行分析和实验。但是你现在所做的就是过早的优化。
- 型@安德烈亚斯,我的优化和算法知识是非常基础的。在这个网站上有很多人对这个话题有更深入的了解,他们能提供比你真正的黑客测试更深刻的见解。此外,这个网站的目的是提出好的问题,这样其他人以后可能会发现它们并从中受益。
- 型@吉姆,你说得对。在我职业生涯的早期,我花了整整一周的时间优化一组复杂的方程(在纸上),然后根据新的方式重新编写程序。新方法比旧方法快200倍,得到了同样的答案。问题是,老办法用了0.8秒。所以我40小时的工作节省了不到一秒钟。
- 型@路易斯维瑟曼,如果我理解你的话…是否正确地说JIT编译器将执行这样的简化/优化?
- 型嗯,可能吧?我不清楚这些转换可以以完全保留语义的方式进行,因为不同分组会产生不同的舍入错误,但是,有什么可能需要优化。
- 型你引用的答案和其他资源不支持你的结论。其中之一是关于整数乘法。在浮点运算中,加减运算的速度较慢。它们中的另一个具体地反驳了您关于程序员应该进行优化的断言。关于十进制和浮点的问题是无关的。其他的则没有定论。本文引用的IBM文章已有15年的历史,早于热点。
- 型@EJP当然不支持我的结论:我没有结论。这就是为什么我问了一个问题,并提供了我在问问题之前尝试过的资源的链接,正如提问帮助中心的第2个主题所建议的那样。
- 型但他们甚至不说你说的话。在大多数情况下,你只是错误地引用了它们,或者引用了无关的东西。只要他们相关并同意,他们就已经回答了你的问题。
- 型@如果我错误地引用了他们中的任何一个,请随意指出/编辑我的问题。每个链接都与我的问题直接相关,但在几乎所有情况下都是一次性的。正如你自己所说,那些不讨论浮点的是"不确定的",随后说他们同意是自相矛盾的。
- @EJP对自己的修正:小数点和浮点之间的连接相互矛盾。(因此我感到困惑。)
- 也许还不如说指令的混合很重要,至少在现代英特尔处理器上是如此。请参阅stackoverflow.com/questions/1146455/…,了解简短的讨论。另请注意第二个答案中的英特尔优化手册链接。记住,处理器本身可以重新排序指令。而细节则随着新芯片设计的改变而改变。您将花费大量时间,并且可能只实现边际性能收益。
- (使用B?,B?,B?而不是用x,y,z:s(b?X-B?y)+(C-1)B?X&178;+(C-1)(B?Y+B?X)-CB?+B?= S(B)?X-B?Y(+)(C-1)(?X+B?Y+B?(z)x?b?)
- 旁注:请记住,算术等价表达式可能具有完全不同的数值稳定性。当然,这取决于应用程序,但是优化正确性(减少错误传播)可能比性能更重要。
型
一般来说,您应该编写最清晰的代码。JIT(不是javac)采用简单、通用的模式并对其进行优化。这意味着使用简单、通用的模式通常是优化代码的最佳方法。
如果您对应用程序进行概要分析,发现代码没有以最佳方式运行,那么您可以尝试自己优化代码;
百万千克1有意义的微观基准很难编写。百万千克1百万千克1结果对环境非常敏感。更改Java或CPU模型的更新,可能会得到冲突的结果。百万千克1百万千克1当您对整个代码进行性能测试时,您可能会发现延迟并不是您期望的那样。例如,它们通常在IO中。百万千克1
型
除非您确信优化确实有帮助,否则您应该坚持使用最简单、最容易维护的代码,并且您可能会发现它运行得足够快。