我们有一个测量数据处理应用程序,目前所有数据都保存为C ++ float
,这意味着我们的x86 / Windows平台上有32bit / 4byte。 (32位Windows应用程序)。
由于精度正在成为一个问题,因此一直在讨论转向另一种数据类型。目前讨论的选项是切换到double
(8字节)或在__int64
(8字节)之上实现固定的十进制类型。
甚至讨论了使用__int64
作为基础类型的固定小数解决方案的原因是有人声称double
性能(仍)明显比处理float
更差,而且我们可能会看到使用本机整数类型存储数字的显着性能优势。 (注意,我们确实可以使用固定的小数精度,尽管代码显然会变得更复杂。)
显然我们最终需要进行基准测试,但是我想问一下,加倍的声明是否会让现代处理器看到真相?我想对于大型阵列双打可能会使缓存命中更加浮动,但是否则我真的看不出它们在性能上会有什么不同?
答案 0 :(得分:5)
这取决于你做了什么。 double
上的加法,减法和乘法与当前x86和POWER架构处理器上float
上的加法,减法和乘法一样快。使用双参数时,除法,平方根和超越函数(exp,log,sin,cos等)通常明显较慢,因为它们的运行时间取决于所需的精度。
如果你去固定点,乘法和除法需要使用长整数乘法/除法指令来实现,这些指令通常比double
上的算术慢(因为处理器的优化程度不高)。更重要的是,如果你在32位模式下运行,需要从几个32位长的乘法中合成长64位乘以128位结果!
缓存利用率在这里是一个红色的鲱鱼。 64位整数和双精度大小相同 - 如果你需要超过32位,无论如何你都会吃掉这个惩罚。
答案 1 :(得分:4)
查一查。英特尔和英特尔都在其网站上的免费PDF文档中公布了CPU的指令延迟。
但是,大部分,性能不会有显着差异,或者有几个原因:
float
vs double
中的一个问题,但如果你不重要则无关紧要与int64
)double
指令可能(我还没有看过)具有比其float
等效时间更长的延迟,但吞吐量是相同的,所以应该可以用doubles
来实现类似的性能。也不是定点数据类型实际上也会更快。它可能,但在某些操作后保持此数据类型一致的开销可能超过节省。浮点运算在现代CPU上相当便宜。它们有一些延迟,但如前所述,它们通常是流水线的,可能会隐藏这个成本。
所以我的建议:
double
版本相对于float
版本的速度慢一点。 float
和double
计算之间是否存在显着的性能差异答案 2 :(得分:3)
我很难理解基本原理“比浮动慢两倍我们将使用64位int”。猜测性能一直是需要大量经验的黑色艺术,在今天的硬件上,考虑到要考虑的因素的数量,它甚至更糟。即使测量也很困难。我知道有几个案例,其中微观基准用于一个解决方案,但在上下文测量中显示另一个更好。
首先要注意的是,解释所声称的浮动性能比浮点性能慢的两个因素在这里并不相关:所需的带宽与双倍的64位int相同,而SSE2向量化将有利于双倍...
然后考虑比使用整数计算会增加整数寄存器和计算单元的压力,显然浮点数将保持不变。 (我已经看到过在double中进行整数计算的情况是由于增加的计算单位而获胜)
所以我怀疑滚动你自己的定点运算比使用double更有利(但我可能会被措施显示错误。)
答案 3 :(得分:2)
实施64个固定点并不是很有趣。特别是对于更复杂的函数,如Sqrt
或对数。对于像添加这样的简单操作,整数可能会更快一些。而且你需要处理整数溢出。并且在实现舍入时需要小心,否则错误很容易累积。
我们在C#项目中实现了固定点,因为我们需要确定性,而.net上的浮点不能保证。这是相当痛苦的。一些公式包含x^3
bang int溢出。除非你有非常令人信服的理由,否则使用float或double而不是fixedpoint。
来自SSE2的SIMD指令进一步使比较复杂化,因为它们允许同时对多个浮点数(4个浮点数或2个双精度数)进行操作。我会使用double并尝试利用这些说明。所以double可能会比浮点数慢得多,但与int相比很难,而且我更喜欢浮点数/双倍超过固定点是大多数场景。
答案 4 :(得分:1)
测量而不是猜测总是最好的。是的,在许多体系结构上,double
上的计算处理数据的两倍,因为float
上的计算(和long double
s的计算速度仍然较慢)。但是,正如其他答案和对此答案的评论所指出的那样,x86架构不遵循与ARM处理器,SPARC处理器等相同的规则。在x86 float
s上,{{1 s和double
都被转换为long double
s进行计算。我应该知道这一点,因为转换导致x86结果比SPARC更准确,并且Sun经历了很多麻烦来获得Java的不太准确的结果,sparking some debate(注意,该页面是从1998年开始的,事情从此改变了。)
此外,long double
的计算内置于CPU中,其中固定十进制数据类型的计算将用软件编写,并且可能更慢。
您应该能够找到一个像样的固定大小的十进制库并进行比较。
答案 5 :(得分:0)
使用各种SIMD指令集,您可以以相同的成本执行4个单精度浮点运算,基本上您可以将4个浮点数打包到一个128位寄存器中。当切换到双打时,你只能将2个双打打包到这些寄存器中,因此你只能同时进行两次操作。
答案 6 :(得分:0)
正如很多人所说的,如果double是一个选项,64位int可能不值得。至少在SSE可用时。这可能在各种微控制器上有所不同,但我想这不是你的应用程序。如果在长浮点数中需要额外的精度,你应该记住this operation is sometimes problematic有浮点数和双精度数,并且在整数上更精确。