25 Aralık 2019 Çarşamba

strictfp Anahtar Kelimesi

Giriş

Java 17 ve Sonrası
Açıklaması şöyle
Java 17 removed the previous default semantic, and all floating-point operations are now done as strict. The keyword strictfp is still there but has no effect and produces a compile-time warning.

Java 17 Öncesi
Açıklaması şöyle. Yani Java 2'den sonra IEEE 754 standardı tam olarak takip edilmiyor.
Java implemented the IEEE 754 standard strictly until Java 1.2 This standard defines not only the format of the numbers when stored in memory but also defines rules how calculations should be executed. After the Java release 1.2 (including 1.2), the standard was released to make the implementations more liberal allowing to use more bits to store intermediate results. This was, and it still is, available on the Intel CPU platforms, and it is used heavily in numeric calculations in other languages like FORTRAN. This was a logical step to allow the implementations to use of this higher precision.

The same time to preserve backward compatibility the strictfp modifier was added to the language. When this modifier is used on a class, interface, or method, the floating point calculations in those codes will strictly follow the IEEE 754 standard.
strictfp Anahtar Kelimesini kullanınca tüm hesaplamalar IEEE 754 standardındaki gibi yapılır. 
Açıklaması şöyle
The strictfp keyword on classes, interfaces and methods forces all intermediate results of floating-point calculations to be IEEE 754 values as well, guaranteeing identical results on all platforms. Without that keyword, implementations can use an extended exponent range where available, resulting in more precise results and faster execution on many common CPUs
strictfp kullanımı bazı CERT-53 tarafından öneriliyor. Açıklaması şöyle.
Programs that require consistent results from floating-point operations across different JVMs and platforms must use the strictfp modifier.
1. Ancak 64 Bit İşlemcilerde strictfp Kullanımı Fark Yaratmaz
Elimizde şöyle bir kod olsun. Bu kod strictfp olsa da olmasa da aynı sonucu verir.
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);
}
Açıklaması şöyle. Sebebi ise 64 bit platformlarda SSE2 instruction set kullanılması. Yani artık FPU 80 bit gibi davranmıyor. SSE2 FPU yazısına bakabilirsiniz.
If by “modern” you mean processors supporting the sort of SSE2 instructions that you quote in your question as produced by your compiler (mulsd, …), then the answer is no, strictfp does not make a difference, because the instruction set does not allow to take advantage of the absence of strictfp. The available instructions are already optimal to compute to the precise specifications of strictfp. In other words, on that kind of modern CPU, you get strictfp semantics all the time for the same price.

If by “modern” you mean the historical 387 FPU, then it is possible to observe a difference if an intermediate computation would overflow or underflow in strictfp mode (the difference being that it may not overflow or, on underflow, keep more precision bits than expected).

2. Eski Sıkıntılar

2.1 64 Bit Olmayan FPU Var Mı ?
X87 FPU eğer programlanmazsa 80 bit çalışıyor.

2.2 X87 FPU İle strictfp Kullanılırsa JVM Ne yapar?
Soru şöyle.
How does(did) a Java runtime targeting an Intel processor without SSE2 deal with floating-point denormals, when strictfp is set?
Cevap şöyle. Yani işlemin sonucunu mutlaka belleğe getirerek ara sonucun FPU'da kalması engelleniyor.
It looks to me, from a very trivial test case, like the JVM round-trips every double computation through memory to get the rounding it wants.
3. IEEE 754 Standardının Takip Edilmemesi Sıkıntı Mıdır?
Eğer 32 bit eski işlemci kullanıyorsak bence sıkıntı, çünkü C# ta aynı Java gibi davranıyor. Yani işlemci ara sonuçları saklamak için daha fazla bit kullanabiliyor. Hatta C# dilinde strictfp diye bir şey yok. Açıklaması şöyle.
Unfortunately there is no way to enforce FP strictness in C#, the .Net CLR just lacks the ability to do calculations with less precision that the maximum that is can.
Dolayısıyla Platform = x86 olarak çalışan C#'taki bir hesaplama ile Java'daki bir hesaplamanın farklı makinelerde aynı sonucu vereceğini garanti edemiyoruz.

4. strictfp Anahtar Kelimesi Nerede Kullanılabilir?
Açıklaması şöyle. Yani strictfp anahtar kelimesi class, interface veya metod üzerinde kullanılabilir.
The strictfp keyword on classes, interfaces and methods forces all intermediate results of floating-point calculations to be IEEE 754 values as well, guaranteeing identical results on all platforms. Without that keyword, implementations can use an extended exponent range where available, resulting in more precise results and faster execution on many common CPUs.
Not : Bu anahtar kelimesi yerine StrictMath sınıfını kullanmak çok daha kolay.

Örnek
Şöyle yaparız.
public strictfp class MyFPclass {
  // ... contents of class here ...
}

Hiç yorum yok:

Yorum Gönder