长双精度浮点数(80位)在使用-funsafe-math-optimizations优化选项时比双精度浮点数快两倍。

4
我发现在使用-funsafe-math-optimizations时,使用long double数据类型进行计算比使用double快大约两倍。我希望能够了解一下这个问题,因为80位格式已经被淘汰很久了,或者我可能在使用double数据类型时做了一些非常愚蠢的事情。编译器是g++ 4.8.2,目标平台是x86_64(所以如果不使用long double,gcc会更喜欢SSE2)。我的代码大致如下(伪代码):
//x is an array of floating point numbers
for i -> x.size
        accumulator = 0
        for k -> kmax
            accumulator += A[k]*(B[k]*cos(C*k*x[i]) - D[k]*sin(C*k*x[i]));
        x[i] += F*accumulator;
        if(x[i] >= 1/2) x[i] -= integer(x[i]+1/2);
        else if(x[i] < -1/2) x[i] -= integer(x[i]-1/2);

AB 等是一些预计算的数组/常量。

加速似乎与缓存行问题无关,因为如果我使用 OpenMP 并行化外部 for 循环,我会获得相同的相对加速。

编辑: 我更正了伪代码:注意 cossin 具有相同的参数,这最终是加速的原因(请参见 gsg 的答案和评论)。


iffor语句的分支历史记录有没有发生变化? - Patricia Shanahan
“the 80 bit format is deprecated since long” 你的出处是什么? - Pascal Cuoq
@Jeff 编译器的输出并没有给我任何特别的见解。但是我不擅长阅读汇编语言。 - Lorenzo Pistone
@LorenzoPistone 你可以确保x86_64目标有SSE2指令,因为这些指令对于这些目标而言是可用的,并且对于floatdouble(binary32和binary64操作)来说确实做到了预期。这并不意味着80位格式已被“弃用”,也不表示您说它已经弃用就是一个来源。 - Pascal Cuoq
@PascalCuoq 正确,不是80位格式,而是整个x87单元。我没有寻找来源,因为您似乎很有知识,并且肯定知道我在引用什么。 - Lorenzo Pistone
显示剩余5条评论
1个回答

2

我猜测差异是由于cos引起的。

long double数学运算必须编译成x87指令,这使得使用x87操作fcos变得容易和高效。然而,对于xmm寄存器没有超越函数操作,因此调用cos必须生成代码将double移动到x87堆栈并调用fcos,或者进行函数调用以完成相同的工作。这些在这个编译器和机器上可能更昂贵。

您可以尝试通过查看汇编来验证这一点-查找call cos或x87指令-并且也值得使用-mfpmath = 387进行编译,以查看性能特征是否改变。


去检查一下。你有解释为什么只有使用-funsafe-math-optimizations才会出现这种情况吗?自从什么时候x87 fcos成为了“不安全”的操作? - Lorenzo Pistone
@LorenzoPistone x87三角函数指令在某些型号的处理器上具有次优的参数简化。请参见http://software.intel.com/en-us/forums/topic/289702。 - Pascal Cuoq
仅凭观察:历史上,gcc通常会发出对cos的调用,除非指定了-ffast-math选项,此时它将使用fcos指令。这个决定可能是因为cos(3)应该为NaN参数设置errno,但我不确定。 - gsg
我在问题中打错了一个字:我没有两个 cos,而是一个 cos 和一个具有相同参数的 sin。我在汇编代码中看到了这条指令 fsincos,我非常确定这就是速度显著提升的原因。如果没有 -funsafe-math-optimizations,我会调用 sincosl - Lorenzo Pistone
@gsg,我接受了你的答案。如果你也提到了fsincos这个东西就更好了。其他操作,比如sqrt,似乎不受是否存在-funsafe-math-optimizations的影响。 - Lorenzo Pistone
是的,如果您同时取相同值的cossin,那么一个高效的编译器将把它们折叠成一个操作(就像div和mod一样,它们可以更有效地一起计算而不是分开计算)。至于sqrt,困难不应该出现,因为有SSE指令专门为double设计了正确的操作。 - gsg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接