32位与64位浮点性能

Any*_*orn 8 floating-point precision performance

我遇到了一个奇怪的问题.我正在研究的算法包含许多像这样的计算

q = x(0)*y(0)*z(0) + x(1)*y(1)*z(1) + ...
Run Code Online (Sandbox Code Playgroud)

总和的长度在4到7之间.

原始计算都是使用64位精度完成的.对于实验,我尝试对x,y,z输入值使用32位精度(以便使用32位执行计算),并将最终结果存储为64位值(直接转换).

我预计32位性能会更好(缓存大小,SIMD大小等),但令我惊讶的是,性能没有差别,甚至可能会降低.

有问题的架构是Intel 64,Linux和GCC.两个代码似乎都使用SSE,两种情况下的数组都与16字节边界对齐.

为什么会这样?到目前为止,我的猜测是32位精度只能在前四个元素上使用SSE,其余的由连续渲染开销连续完成.

dsi*_*cha 24

至少在x87上,一切都是在内部以80位精度完成的.精度实际上只决定了这些位中有多少存储在内存中.这是为什么不同的优化设置可以稍微改变结果的部分原因:它们将舍入量从80位更改为32位或64位.

实际上,使用80位浮点(long double在C和C++中,real在D中)通常很慢,因为没有有效的方法从内存加载和存储80位.32位和64位通常同样快,前提是内存带宽不是瓶颈,即无论如何一切都在缓存中.如果发生以下任一情况,64位可能会更慢:

  1. 内存带宽是瓶颈.
  2. 64位数字未在8字节边界上正确对齐.32位数字只需要4字节对齐以获得最佳效率,因此它们不那么挑剔.一些编译器(数字Mars D编译器浮现在脑海中)并不总是能够正确地存储在堆栈中的64位双精度数.这导致加载一次所需的内存操作量的两倍,实际上与正确对齐的64位浮点数或32位浮点数相比,导致大约2倍的性能损失.

就SIMD优化而言,应该注意的是大多数编译器在自动矢量化代码方面都很糟糕.如果您不想直接使用汇编语言编写,那么利用这些指令的最佳方法是使用类似于数组的操作,例如,在D中可用,并根据SSE指令实现.类似地,在C或C++中,你可能想要使用SSE优化的高级函数库,虽然我不知道一个很好的函数,因为我主要在D编程.

  • "x87" - 比那些旧的x86处理器略胜一筹.:-) (4认同)