【问题标题】:Retain bit-exact floating point calculations on AArch64 with O2使用 O2 在 AArch64 上保留位精确浮点计算
【发布时间】: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

标签: c gcc arm arm64 fpu


【解决方案1】:

根据您对 ARMv7-A 构建的选择(如果您使用的是 -mfpu=vfpv4 或同等版本,则此答案可能是错误的)您看到的最有可能的差异将是 FMA 操作的生成。

为避免这种情况,请使用-ffp-contract=off。此选项的GCC documentation 表示:

-ffp-contract=style

-ffp-contract=off 禁用浮点表达式收缩。

-ffp-contract=fast 启用浮点表达式收缩,例如 如果目标具有本机,则作为融合乘加运算的形成 支持他们。

-ffp-contract=on 启用浮点表达式 在语言标准允许的情况下收缩。这目前不是 实施和处理等于-ffp-contract=off

默认为-ffp-contract=fast

【讨论】:

    猜你喜欢
    • 2022-01-22
    • 2017-03-29
    • 1970-01-01
    • 1970-01-01
    • 2019-01-10
    • 2015-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多