【发布时间】:2016-04-21 09:30:26
【问题描述】:
我正在使用浮点数学比较信号处理库的输出,它是为 AArch64 (ARMv8) 构建的,使用例如GCC 4.9。
根据优化级别会出现差异。未优化的构建 (O0) 计算相对于 ARMv7 引用的位精确结果。在 ARMv7 环境中,“O2”构建不会在浮点计算中引入偏差。 对于 ARMv8,情况并非如此。优化的构建实际上计算出不同的结果。
是否可以使用编译器开关来保持非优化构建的位精确性?
已在 DragonBoard 410c (Cortex-A53) 上进行了测试。
【问题讨论】:
-
硬件执行相同的 FP 操作。您看到的差异可能是由于引入了 SIMD 操作,它可以改变总浮点操作的数量。例如,如果您一次添加一个数字列表,则与将它们 4 乘 4 相加,然后将最后一个 4 相加作为最后一步,您将得到不同的结果。每个 FP 操作都会引入一个轻微的错误;用得越多,误差就越大。
-
我知道浮点关联性很关键。即使 O2 处于活动状态,ARMv7 的编译器仍然能够确保位完美的处理。现在至少在我对 DragonBoard 的第一次测试中,ARMv8 似乎并非如此。可能是硬件故障或编译器属性(或预期行为)。
-
对差异的最可能解释是浮点寄存器有时比
double大。优化后,编译器通常会将中间结果保存在浮点寄存器中,其效果是结果比将值存储到内存时获得的结果更准确,但又有所不同。如果您使用gcc,请尝试指定此选项:-ffloat-store这将禁止大多数可能导致浮点结果更改的优化。 -
在 armv7 上,小于
-Ofast的优化设置必须使用 VFP 浮点指令,因为 NEON 不符合 ieee754(将非规范化视为零)。在armv8上,NEON支持ieee754,所以编译器可以使用。 -
清除其中一些 cmets... GCC 不会在
-O2重新关联 FP 数学,除非您给它一个轻松的-ffast-math选项。 AArch64 不会在更宽的寄存器模式下计算 64 位浮点数(所以-ffloat-store不会有帮助),并且可以依靠 C 编译器在优化级别和架构之间产生可移植的结果(只要您不在放宽标准的模式下)。 ARMv8-A 在 Neon 中支持完整的 IEEE754,但仅在 AArch64 模式下。这里最可能的问题是 FMA 指令。尝试设置-ffp-contract=off。