Java strictfp 修饰符对现代 CPU 有什么影响吗?
根据JLS,我知道方法(和类)上修饰符的含义:strictfp
strictfp 修饰符的作用是使方法主体中的所有浮点表达式或双精度表达式都显式为 FP-strict (§15.4)。
在 FP 严格表达式中,所有中间值都必须是浮点值集或双精度值集的元素,这意味着所有 FP 严格表达式的结果必须是 IEEE 754 算术对使用单一和双精度格式表示的操作数预测的结果。
在不严格 FP 的表达式中,为实现提供了一些余地,以使用扩展的指数范围来表示中间结果;粗略地说,净效应是,在排除使用浮点值集或双精度值集可能导致溢出或下溢的情况下,计算可能会产生“正确答案”。
我一直在尝试想出一种方法来获得方法中的表达式与非.我已经在两台笔记本电脑上尝试过,一台使用Intel Core i3 CPU,另一台使用Intel Core i7 CPU。我得不到任何区别。strictfp
strictfp
许多帖子表明,不使用 的原生浮点数可能使用 80 位浮点数,并且在最小可能的 java 双精度值(最接近零)或高于可能的最高 64 位 java 双精度值时,具有额外的可表示数字。strictfp
我在下面尝试了带和不带修饰符的代码,它给出了完全相同的结果。strictfp
public static strictfp void withStrictFp() {
double v = Double.MAX_VALUE;
System.out.println(v * 1.0000001 / 1.0000001);
v = Double.MIN_VALUE;
System.out.println(v / 2 * 2);
}
实际上,我假设任何差异只会在代码编译为程序集时才会出现,因此我使用JVM参数运行它。但没有区别。-Xcomp
我发现另一篇文章解释了如何获取HotSpot生成的汇编代码(OpenJDK文档)。我正在使用 运行我的代码。带有修饰符的第一个表达式 ()(如果没有修饰符的表达式也是如此)被编译为:java -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
v * 1.0000001 / 1.0000001
strictfp
0x000000010f10a0a9: movsd -0xb1(%rip),%xmm0 # 0x000000010f10a000
; {section_word}
0x000000010f10a0b1: mulsd -0xb1(%rip),%xmm0 # 0x000000010f10a008
; {section_word}
0x000000010f10a0b9: divsd -0xb1(%rip),%xmm0 # 0x000000010f10a010
; {section_word}
该代码中没有任何内容像我预期的那样将每个步骤的结果截断到64位。查找 的文档,它们都提到这些 (SSE) 指令对 64 位浮点值运行,而不是像我预期的那样对 80 位值运行。因此,这些指令操作的双值集已经是IEEE 754值集似乎是合乎逻辑的,因此拥有和没有它之间没有区别。movsd
mulsd
divsd
strictfp
我的问题是:
- 这种分析是否正确?我不经常使用英特尔汇编,所以我对我的结论没有信心。
- 是否有任何(其他)现代CPU架构(具有JVM)在有和不带修饰符的操作之间存在差异?
strictfp