什么是浮点增加对浮点乘法的相对速度(What's the relative speed of

2019-06-17 10:27发布

一,二十年前,它是值得写的数字代码以避免使用乘,除和使用加法和减法来代替。 一个很好的例子是使用前向差分来评价多项式曲线,而不是直接在计算多项式的。

这仍然是这样,还是有现代计算机体系结构进展到*,/不再是许多倍+,慢点 - ?

具体而言,我感兴趣的是编译的C / C ++代码,具有丰富的板载浮点硬件上现代典型的x86芯片上运行,而不是一个小型微型试图做FP软件。 我意识到流水线等建筑增强排除特定的周期数,但我仍希望得到一个有用的直觉。

Answer 1:

这也取决于指令混合。 您的处理器将有多个计算单元随时待命,如果所有的人都被填充了所有的时间,你会得到最大的吞吐量。 因此,执行MUL的的循环是一样快执行循环或添加 - 但如果表达式变得更加复杂,同样不成立。

例如,以此循环:

for(int j=0;j<NUMITER;j++) {
  for(int i=1;i<NUMEL;i++) {
    bla += 2.1 + arr1[i] + arr2[i] + arr3[i] + arr4[i] ;
  }
}

对于NUMITER = 10 ^ 7,NUMEL = 10 ^ 2,初始化为小的正数(NaN的是慢得多)两个阵列,这需要使用一个64位的PROC双打6.0秒。 如果我更换了与环

bla += 2.1 * arr1[i] + arr2[i] + arr3[i] * arr4[i] ;

只需要1.7秒......所以,因为我们“过火”的补充,该MULS基本上免费的; 在增加的减少帮助。 它得到的更多的困惑:

bla += 2.1 + arr1[i] * arr2[i] + arr3[i] * arr4[i] ;

- 同一MUL /添加分布,但现在的常数加入,而不是相乘 - 需要3.7秒。 您的处理器很可能优化以更高效地执行典型数值计算; 所以点积状MULS的金额和比例的款项是因为它得到一样好; 添加常数是几乎没有共同的,所以这是比较慢...

bla += someval + arr1[i] * arr2[i] + arr3[i] * arr4[i] ; /*someval == 2.1*/

再次需要1.7秒。

bla += someval + arr1[i] + arr2[i] + arr3[i] + arr4[i] ; /*someval == 2.1*/

(同初始循环,但无需昂贵的恒定添加2.1秒)的

bla += someval * arr1[i] * arr2[i] * arr3[i] * arr4[i] ; /*someval == 2.1*/

(主要是MULS,但除了一个1.9秒为单位)

所以,基本上; 很难说这是更快,但如果你希望避免的瓶颈,更重要的是要有一个清醒的搭配,避免NaN或INF,避免增加常量。 不管你做什么,一定要进行测试,并且测试不同的编译器设置,因为经常微小变化可能只是赚取差价。

一些更多的情况:

bla *= someval; // someval very near 1.0; takes 2.1 seconds
bla *= arr1[i] ;// arr1[i] all very near 1.0; takes 66(!) seconds
bla += someval + arr1[i] * arr2[i] + arr3[i] * arr4[i] ; // 1.6 seconds
bla += someval + arr1[i] * arr2[i] + arr3[i] * arr4[i] ; //32-bit mode, 2.2 seconds
bla += someval + arr1[i] * arr2[i] + arr3[i] * arr4[i] ; //32-bit mode, floats 2.2 seconds
bla += someval * arr1[i]* arr2[i];// 0.9 in x64, 1.6 in x86
bla += someval * arr1[i];// 0.55 in x64, 0.8 in x86
bla += arr1[i] * arr2[i];// 0.8 in x64, 0.8 in x86, 0.95 in CLR+x64, 0.8 in CLR+x86


Answer 2:

从理论上来说,信息是在这里:

Intel®64和IA-32架构优化参考手册,附录C INSTRUCTION延迟和吞吐量

对于他们列出每一个处理器,在FMUL的潜伏期是非常接近FADD或FDIV的。 在一些较老的处理器,FDIV为2-3倍比慢,而在较新的处理器,这是一样的FMUL。

注意事项:

  1. 我其实链接的文档说,你不能依赖于现实生活中的这些数字,因为该处理器将做它想使事情更快,如果它是正确的。

  2. 有一个很好的机会,你的编译器将决定使用具有浮点乘法/除法提供的许多新指令集的一个。

  3. 这是一个复杂的文件只是为了通过编译器作者阅读和我可能会得到它错了。 像我不清楚为什么FDIV延迟数是完全针对一些CPU的缺失。



Answer 3:

回答这个问题的最好办法就是实际写你需要做的处理的基准/轮廓。 实证应在理论被用来当过可能的。 特别是当它很容易实现。

如果你已经知道你需要做数学的不同实现,你可以写数学的AA几个不同的代码transfermations,看看你的表现峰。 这将允许处理器/编译器产生不同的执行流,以填补处理器管线,给你一个具体的答案来回答。

如果你是在DIV / MUL / ADD / SUB类型说明具体性能感兴趣,你可以在一些内联汇编甚至折腾专门控制其执行这些指令的变体。 但是,你需要确保你保持multilple执行单元忙来获得性能的系统能够一个好主意。

还做这样的事情会让您只需在其上运行同一程序来比较处理器的多种变体的性能,而且还可以让你在主板的差异因素。

编辑:

A +的基本架构 - 是相同的。 因此,他们在逻辑上采取相同的时间来计算。 *在另一方面,需要多个层,典型地构造出“全加器”来完成一个单一的操作。 这garentees说,虽然*可以颁发给流水线每个周期将有比加/减电路较高的延迟。 甲FP /操作是使用其迭代地朝着随时间的正确答案收敛的近似方法典型地实现。 这些类型的近似值的经由乘法典型地实施。 因此,对于浮点一般可以假设,因为这是不切实际的“展开”乘法除法将需要更长的时间(这已经是它的自我和大量电路)到乘法器电路众多的管道。 仍然给定系统的性能最好通过试验测定的。



Answer 4:

我无法找到一个明确的参考,但大量的实验告诉我,浮动乘法现在差不多是相同的速度,加减,而分工不(但不是“很多次”慢,要么)。 你可以让你只运行自己的实验愿望的直觉 - 记得提前产生的随机数(百万人),阅读您开始计时前,并使用CPU的性能计数器(没有其他进程运行,如就像你可以从)进行精确测量阻止他们!



Answer 5:

* / VS +的速度差 - 取决于你的处理器架构。 特别是在一般的x86速度差已变得不那么有现代的处理器。 *应接近+,当有疑问:只是实验。 如果你有大量的FP操作的一个很艰难的问题,也可以考虑使用你的GPU(的GeForce,...),它可以作为一个向量处理器。



Answer 6:

有可能是在乘法和加法之间的时间相差无几。 在另一方面师是因为它的递归性质仍然显著慢然后乘法。 现代x86架构的SSE指令应该做浮点运算时,而不是使用fpu.Though良好的C / C ++编译器应该给你用的,而不是FPU上证所的选择加以考虑。



文章来源: What's the relative speed of floating point add vs. floating point multiply