在使用 -funsafe-math-optimizations
。我想对此有所了解,因为 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);
A
, B
, .. 是一些预先计算的数组/常量。
加速似乎与缓存行问题无关,因为如果我将外部 for 循环与 OpenMP 并行化,我将获得相同的相对加速。
编辑:
我更正了伪代码:注意 cos
和 sin
有相同的参数,这最终是加速的原因(参见 gsg 的回答和评论)。
最佳答案
我的猜测是,差异是由于 cos
造成的。
long double
数学运算必须编译成 x87 指令,这样可以轻松高效地使用 x87 操作 fcos
。但是,xmm
寄存器没有超越操作,因此对 cos 的调用必须生成代码以将 double
移动到 x87 堆栈并调用 fcos
,或者调用一个函数来做同样的工作。这些对于这个编译器和机器来说可能更昂贵。
您可以尝试通过查看程序集来验证这一点 - 寻找 call cos
或 x87 指令 - 也可能值得使用 -mfpmath=387
编译到查看性能特征是否发生变化。
关于c - long double(80 位)是使用 -funsafe-math-optimizations 的两倍快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20602599/