JIT 是否使用 /F:fast 或 /F:precise 处理浮点运算
Does the JIT process floating point arithmetic with /F:fast or /F:precise
在 C++ 优化器中,您可以指定使用快速浮点运算而不是精确浮点运算。不同之处在于,在快速模式下,它会进行适用于现实世界数学的优化,但在计算机上完成时可能不会产生正确的结果。
可以使用 GodBolt 使用以下代码和 -O2
优化来展示这方面的示例。如果您使用的是 clang 或 gcc,您可以输入 -ffast-math
参数来查看这些优化后的代码。
double mulBy6DivBy12(double x)
{ return 6 * x / 12; }
double divBy2(double x)
{ return x / 2; }
如果没有-ffast-math
参数,它会在mulBy6DivBy12
函数中生成一个乘法和除法运算,有它在两个函数上看起来是一样的。
我想知道的是在运行时,当被 JIT 处理时,它是否进行了这些潜在的不安全优化?
Java 语言规范中有两个有趣的陈述。
第一个是广义的in JLS section 15.7:
15.7. Evaluation Order
The Java programming language guarantees that the operands of
operators appear to be evaluated in a specific evaluation order,
namely, from left to right.
这已经是完全的保证了;即使可以按任何顺序执行,它们也必须 看起来 从左到右的评估顺序。浮点运算的重新排序会破坏外观,因此不允许。
其次,有一个专门针对浮点运算的保证in JLS section 4.2.4:
The Java programming language requires that floating-point arithmetic
behave as if every floating-point operator rounded its floating-point
result to the result precision. Inexact results must be rounded to the
representable value nearest to the infinitely precise result; if the
two nearest representable values are equally near, the one with its
least significant bit zero is chosen. This is the IEEE 754 standard's
default rounding mode known as round to nearest.
这清楚地阐明了每个(从左到右)操作应该如何舍入其结果。这也不允许任何改变计算结果的重新排序,如果您以从左到右的顺序执行操作时得到的结果。
在 C++ 优化器中,您可以指定使用快速浮点运算而不是精确浮点运算。不同之处在于,在快速模式下,它会进行适用于现实世界数学的优化,但在计算机上完成时可能不会产生正确的结果。
可以使用 GodBolt 使用以下代码和 -O2
优化来展示这方面的示例。如果您使用的是 clang 或 gcc,您可以输入 -ffast-math
参数来查看这些优化后的代码。
double mulBy6DivBy12(double x)
{ return 6 * x / 12; }
double divBy2(double x)
{ return x / 2; }
如果没有-ffast-math
参数,它会在mulBy6DivBy12
函数中生成一个乘法和除法运算,有它在两个函数上看起来是一样的。
我想知道的是在运行时,当被 JIT 处理时,它是否进行了这些潜在的不安全优化?
Java 语言规范中有两个有趣的陈述。
第一个是广义的in JLS section 15.7:
15.7. Evaluation Order
The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.
这已经是完全的保证了;即使可以按任何顺序执行,它们也必须 看起来 从左到右的评估顺序。浮点运算的重新排序会破坏外观,因此不允许。
其次,有一个专门针对浮点运算的保证in JLS section 4.2.4:
The Java programming language requires that floating-point arithmetic behave as if every floating-point operator rounded its floating-point result to the result precision. Inexact results must be rounded to the representable value nearest to the infinitely precise result; if the two nearest representable values are equally near, the one with its least significant bit zero is chosen. This is the IEEE 754 standard's default rounding mode known as round to nearest.
这清楚地阐明了每个(从左到右)操作应该如何舍入其结果。这也不允许任何改变计算结果的重新排序,如果您以从左到右的顺序执行操作时得到的结果。