Влияет ли модификатор Java strictfp на современные процессоры?
Я знаю значениеstrictfp
модификатор методов (и классов) в соответствии с JLS:
Эффект модификатора strictfp заключается в том, чтобы сделать все выражения с плавающей запятой или двойные выражения в теле метода явным образом строгим по FP (§15.4).
JLS 15.4 FP-строгие выражения:
В выражении строгого FP все промежуточные значения должны быть элементами набора значений с плавающей запятой или набора двойных значений, подразумевая, что результаты всех выражений строгого FP должны быть теми, которые предсказаны арифметикой IEEE 754 для операндов, представленных с использованием одинарного и двойного форматов. ,
В выражении, которое не является строгим по FP, предоставляется некоторая свобода для реализации, чтобы использовать расширенный диапазон экспонент для представления промежуточных результатов; общий эффект, грубо говоря, состоит в том, что вычисление может дать «правильный ответ» в ситуациях, когда исключительное использование набора значений с плавающей запятой или набора двойных значений может привести к переполнению или потере.
Я пытался придумать способ получить реальную разницу между выражением вstrictfp
метод и тот, который неstrictfp
, Я пробовал это на двух ноутбуках, один с процессором Intel Core i3 и один с процессором Intel Core i7. И я не могу получить никакой разницы.
Многие посты предполагают, что родная с плавающей точкой, не используяstrictfp
, может использовать 80-битные числа с плавающей запятой и иметь дополнительные представимые числа ниже наименьшего возможного java double (ближайшего к нулю) или выше максимально возможного 64-битного java double.
Я попробовал этот код ниже с и без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);
}
На самом деле, я предполагаю, что любая разница будет проявляться только тогда, когда код скомпилирован в сборку, поэтому я запускаю его с-Xcomp
Аргумент JVM. Но без разницы.
я нашелдругой пост объяснение того, как вы можете получить код сборки, сгенерированный 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 бит, как я ожидал.Глядя вверх документация изmovsd
, mulsd
а такжеdivsd
все они упоминают, что эти (SSE) инструкции работают с 64-битными значениями с плавающей запятой, а не с 80-битными, как я ожидал. Таким образом, кажется логичным, что двойной набор значений, над которым работают эти инструкции, уже является набором значений IEEE 754, поэтому не было бы никакой разницы междуstrictfp
и не имея этого.
Мои вопросы:
Является ли этот анализ правильным? Я не часто использую сборку Intel, поэтому я не уверен в своем заключении.Существует ли какая-либо (другая) современная архитектура ЦП (в которой есть JVM), для которой есть разница между работой с и безstrictfp
модификатор?