我正在阅读Agner Fog的优化手册,并且遇到了这个例子:
double data[LEN];
void compute()
{
const double A = 1.1, B = 2.2, C = 3.3;
int i;
for(i=0; i<LEN; i++) {
data[i] = A*i*i + B*i + C;
}
}
Run Code Online (Sandbox Code Playgroud)
Agner 指出,有一种方法可以优化此代码 - 通过认识到循环可以避免使用昂贵的乘法,而是使用每次迭代应用的“增量”。
我用一张纸来证实这个理论,首先......
...当然,他是对的 - 在每次循环迭代中,我们可以通过添加“增量”,基于旧结果计算新结果。该增量从值“A+B”开始,然后每一步增加“2*A”。
所以我们将代码更新为如下所示:
void compute()
{
const double A = 1.1, B = 2.2, C = 3.3;
const double A2 = A+A;
double Z = A+B;
double Y = C;
int i;
for(i=0; i<LEN; i++) {
data[i] …Run Code Online (Sandbox Code Playgroud) 通过编码是否有任何(非微优化)性能增益
float f1 = 200f / 2
Run Code Online (Sandbox Code Playgroud)
在比较中
float f2 = 200f * 0.5
Run Code Online (Sandbox Code Playgroud)
几年前我的一位教授告诉我,浮点除法比浮点乘法慢,但没有详细说明原因.
这句话适用于现代PC架构吗?
UPDATE1
关于评论,请同时考虑这个案例:
float f1;
float f2 = 2
float f3 = 3;
for( i =0 ; i < 1e8; i++)
{
f1 = (i * f2 + i / f3) * 0.5; //or divide by 2.0f, respectively
}
Run Code Online (Sandbox Code Playgroud)
更新2 从评论中引用:
[我想]知道什么是算法/架构要求导致>除法在硬件上比复制要复杂得多
我写了这个:
var max = 0xffffff * 4;
var step = 1 / max;
function cube() {
var result = 0.;
for (var x = 0.; x < 1; x += step) {
result += x * x * x;
}
return result;
}
function mul() {
var result = 0.;
for (var x = 0.; x < 1; x += step) {
result += x * x;
}
return result;
}
function go() {
var r = '';
r += …Run Code Online (Sandbox Code Playgroud) 我正在编写一个非常重的JavaScript应用程序(它几乎都是JavaScript),并且它确实需要大量的数据来迭代(JSON),并且必须执行算术某些任务.性能是该应用程序的主要考虑因素.我已经介绍了Webworkers以帮助解决这个问题,并且我试图不依赖于像jQuery这样的lib提供的方法(.each()而不是for循环).无论如何,这是一个简单的问题......
在申请中,我必须应用价格变化,这将涉及许多涉及分割的数字过程.记住,这将发生成千上万次对我来说总是通过乘法或乘法和除法的混合来应用变化会更好.例如,我可以通过乘以0.5或除以2来应用50%的折扣.
我总是被告知分裂比乘法慢,但我没有真正的证据......在开始基准测试和运行测试之前,有没有人对此有意见?
我是航空航天工程和EECS学生.我正处于大量数学和物理学的工作,但尚未进入算法或汇编语言.
我设计和编写了各种各样的程序,从商业建议软件到卫星硬件控制器.
这项工作大部分涉及在其他媒介中进行数学运算,然后编写代码来实现它.
在将它们放入代码之前,我代数地简化了这些方程式.但是在我花时间这么做之前,我想知道我是否应该支持更多的加法运算,或者更多的乘法运算.(我已经知道分工的成本要高得多.)
这是我从其他一些工作中得出的等式,这是我所看到的非常典型的.
我们可以清楚地看到,至少有一些方法可以简化这个等式.由于简化是我的决定,我想挑选尽可能多的有利于性能的选项实用.我不打算以算法设计时为代价获得前沿性能.
一般来说,哪种双重操作更快:加法或乘法?
我知道知道哪个更快的唯一明确方法是编写和运行基准测试,但这不是重点.对于每次我需要简化方程式时编写测试代码的合理性,这不是一个足够高的优先级.我需要的是一个适用于我的代数的经验法则.
如果差异是如此微小,以至于边界可忽略不计或不确定,这是一个可以接受的答案,只要我知道它几乎没有区别.
我知道,在C和C++中,优化器会处理代数,因此它是一个空问题.但是,据我所知,Java编译器不进行代数简化/优化.具体来说,这个答案表明情况就是这样,程序员应该进行这种优化.
互联网上存在分散的答案,但我无法得出确凿的答案.一位前马里兰大学物理系的学生在Java上运行这些测试,但表中没有双重性能数据,图表比例使结果难以辨认.这个魁北克大学CS教授的测试只揭示了整数运算的结果.这个SO答案解释说,在硬件层面上,乘法是一个更复杂的操作,但我也意识到工程师在设计处理器时要记住这些事情.
其他有用的链接:
我们可以用C/C++中的左移位运算符来更快地将整数乘以2的幂.
但我们不能将左移运算符用于浮点数或双精度数,因为它们以不同的方式表示,具有指数分量和尾数分量.
我的问题是,
有什么办法吗?像左移运算符的整数更快地乘以浮点数?即使有2的幂?
performance ×3
c++ ×2
javascript ×2
optimization ×2
algorithm ×1
assembly ×1
c ×1
double ×1
java ×1
simd ×1
x86-64 ×1