¿Cuándo debo usar la palabra clave "strictlyfp" en Java?


258

He buscado lo que esto hace, pero ¿alguien tiene un ejemplo de cuándo usarías la strictfppalabra clave en Java? ¿Alguien realmente ha encontrado un uso para esto?

¿Habría algún efecto secundario de ponerlo en todas mis operaciones de coma flotante?


1
Siempre, a menos que realmente necesite el rendimiento más de lo que necesita reproducibilidad.
Antimonio

1
@Antimony - o la precisión / corrección. x86 / x64, por ejemplo, utiliza registros de coma flotante de 80 bits internamente, por lo que el resultado será más preciso para un cálculo largo sin estricto fp.
Robert Fraser

1
@Robert En realidad, la especificación garantiza una precisión limitada de la mantisa. La única diferencia es que puede usar una precisión de exponente mayor que la normal, lo que tiene diferencias en casos raros debido al doble redondeo.
Antimonio

Estoy pensando que, además de la opción de rociar este útil modificador alrededor de la unión, los nuevos tipos de datos sfloat y sdouble primitive absolutefp podrían ser una buena idea.
theRiley

Respuestas:


274

Strictfp garantiza que obtenga exactamente los mismos resultados de sus cálculos de coma flotante en cada plataforma. Si no usa strictlyfp, la implementación de JVM es libre de usar precisión adicional donde esté disponible.

De la JLS :

Dentro de una expresión estricta de FP, todos los valores intermedios deben ser elementos del conjunto de valores flotantes o del conjunto de valores dobles, lo que implica que los resultados de todas las expresiones estrictas de FP deben ser los pronosticados por la aritmética IEEE 754 en operandos representados con formatos simples y dobles . Dentro de una expresión que no es estrictamente FP, se concede margen de maniobra para que una implementación use un rango de exponente extendido para representar resultados intermedios; El efecto neto, en términos generales, es que un cálculo puede producir "la respuesta correcta" en situaciones en las que el uso exclusivo del conjunto de valores flotantes o el conjunto de valores dobles puede dar como resultado un desbordamiento o un subflujo.

En otras palabras, se trata de asegurarse de que Write-Once-Run-Anywhere realmente signifique Write-Once-Get-Equally-Wrong-Results-Everywhere .

Con strictlyfp, sus resultados son portátiles, sin ellos es más probable que sean precisos.


28
Úselo para obtener resultados científicos reproducibles y pruebas unitarias de bits exactos.
Aleksandr Dubinsky

1
"Si no usas estrictamente fp, la implementación de JVM es libre de usar precisión adicional donde esté disponible" - lo haces sonar como algo malo: P
AMDG

@LinkTheProgrammer ciertamente puede ser algo malo
Tim

@TimCastelijns ¿Supongo que Happy Wheels es tu referencia? Las repeticiones graban pulsaciones de teclas; debido a la diversidad de precisión de implementación de FP-math, las repeticiones solo son precisas en hardware similar. ¿Puedes nombrar un problema más realista causado por la variabilidad matemática de coma flotante? Me imagino quizás un simulador de partículas, pero ¿qué más?
AMDG

Entonces, ¿esto significa que siempre deberíamos usar estrictofp en la producción donde intervienen múltiples plataformas?
Beatrice

65

Wikipedia en realidad tiene un buen artículo sobre este tema aquí , con un enlace a la especificación de Java.

Leyendo entre líneas, la implicación es que si no especifica strictfp, entonces el compilador JVM y JIT tiene licencia para calcular sus cálculos de punto flotante como quiera. En aras de la velocidad, lo más probable es que deleguen el cálculo a su procesador. Con strictfpon, los cálculos deben cumplir con los estándares aritméticos IEEE 754, lo que, en la práctica, probablemente significa que la JVM hará el cálculo.

Entonces, ¿por qué quieres usar strictfp? Un escenario que puedo ver es en una aplicación distribuida (o juego multijugador) donde todos los cálculos de punto flotante deben ser deterministas sin importar cuál sea el hardware o CPU subyacente. ¿Cuál es la compensación? Tiempo de ejecución más probable.


55
"Un rango de exponente extendido para representar resultados intermedios" no es una "licencia para calcular sus cálculos de coma flotante como quieran", y en la práctica, incluso los strictfpcálculos utilizan incluso una FPU 8087 inútil. Es solo el caso que se requiere un poco de cuidado entonces. Ver stackoverflow.com/questions/18496560/…
Pascal Cuoq

Estoy de acuerdo con @PascalCuoq re: "licencia para calcular sus cálculos de coma flotante como quieran" . En todo caso, lo contrario parece ser cierto en este caso, ya que strictfpgarantiza el cumplimiento del estándar IEEE 754 (para que obtenga el mismo resultado en todas las plataformas). El único inconveniente que puedo ver es que puede perder los beneficios de tener una FPU realmente buena disponible en su hardware nativo.
typeracer

25

Todo comenzó con una historia,

Cuando java estaba siendo desarrollado por James Gosling, Herbert y el resto de su equipo. Tenían en mente esta locura llamada independencia de la plataforma . Querían hacer roble (Java)tanto mejor que funcionaría exactamente igual en cualquier máquina que tenga un conjunto de instrucciones diferente, incluso ejecutando diferentes sistemas operativos. Pero había un problema con los números de punto decimal también conocidos como coma flotante y doble en los lenguajes de programación. Algunas máquinas se construyeron con objetivos de eficiencia, mientras que el resto tenían objetivos de precisión. Entonces, las máquinas posteriores (más precisas) tenían un tamaño de coma flotante de 80 bits, mientras que las máquinas anteriores (más eficientes / más rápidas) tenían dobles de 64 bits. Pero, esto estaba en contra de la idea central de construir un lenguaje independiente de la plataforma. Además, esto podría conducir a la pérdida de precisión / datos cuando se construye un código en alguna máquina (que tiene el doble del tamaño de 64 bits) y se ejecuta en otro tipo de máquina (que tiene el doble del tamaño de 80 bits).

El tamaño ascendente puede tolerarse, pero el tamaño descendente no puede serlo. Entonces, se encontraron con un concepto de estricto fp, es decir, coma flotante estricto . Si usa esta palabra clave con una clase / función, entonces su punto flotante y sus dobles tienen un tamaño consistente sobre cualquier máquina. es decir, 32/64 bits, respectivamente.


8
strictlyfp se introdujo en Java 1.2. Esto fue mucho más tarde que cuando se diseñó el roble.
Thorbjørn Ravn Andersen

"números de coma decimal también conocidos como coma flotante" - Decimal significa base 10, y no tiene nada que ver con representaciones de coma flotante.
aioobe 01 de

21

Aquí hay varias referencias:

  • Uso de strictlyfp (Consejo técnico de JDC)
  • jGuru: ¿ Para qué es el modificador strictlyfp? ¿Cuándo consideraría usarlo?

    Básicamente, todo se reduce a si le importa o no que los resultados de las expresiones de punto flotante en su código sean rápidos o predecibles. Por ejemplo, si necesita las respuestas de su código que utiliza valores de punto flotante para ser coherente en múltiples plataformas, utilice strictfp.

  • strictlyfp - Glosario de Java

    El hardware de punto flotante calcula con mayor precisión y con un rango de valores mayor que el que requiere la especificación Java. Sería confuso si algunas plataformas dieran más precisión que otras. Cuando utiliza el strictfpmodificador en un método o clase, el compilador genera código que se adhiere estrictamente a la especificación de Java para obtener resultados idénticos en todas las plataformas. Sin esto strictfp, es un poco más laxo, pero no tanto como para usar los bits de protección en el Pentium para dar 80 bits de precisión.

  • Y, por último, la especificación del lenguaje Java real, §15.4 Expresiones estrictas de FP :

    Dentro de una expresión estricta de FP, todos los valores intermedios deben ser elementos del conjunto de valores flotantes o del conjunto de valores dobles, lo que implica que los resultados de todas las expresiones estrictas de FP deben ser los pronosticados por la aritmética IEEE 754 en operandos representados con formatos simples y dobles . Dentro de una expresión que no es estrictamente FP, se concede margen de maniobra para que una implementación use un rango de exponente extendido para representar resultados intermedios; El efecto neto, en términos generales, es que un cálculo puede producir "la respuesta correcta" en situaciones en las que el uso exclusivo del conjunto de valores flotantes o el conjunto de valores dobles puede dar como resultado un desbordamiento o un subflujo.

Sin embargo, nunca he tenido un uso personal.


12

Como se mencionó en las otras respuestas, los resultados de punto flotante intermedio se ajustan a la especificación IEEE. En particular, los procesadores x86 pueden almacenar resultados intermedios con una precisión diferente de la especificación IEEE. La situación se vuelve más complicada cuando el JIT optimiza un cálculo particular; El orden de las instrucciones puede ser diferente cada vez, lo que da como resultado un redondeo ligeramente diferente.

La sobrecarga en la que incurrió estrictofp probablemente dependerá mucho del procesador y del JIT. Este artículo de Wikipedia sobre SSE2 parece tener una idea del problema. Entonces, si el JIT puede generar instrucciones SSE para realizar un cálculo, parece que estrictafp no tendrá ninguna sobrecarga.

En mi proyecto actual, hay algunos lugares donde utilizo estrictamentefp. Hay un punto en el que los rayos cósmicos potenciales deben eliminarse de los valores de píxeles. Si algún investigador externo tiene el mismo valor de píxel y rayos cósmicos frente a ellos, debería obtener el mismo valor resultante que nuestro software.


8
  • strictlyfp es un modificador que restringe los cálculos de coma flotante según IEEE 754.

  • Esto se puede usar en toda la clase como "public divinefp class StrictFpModifierExample {}" o en el método "public strictfp void example ()". Si se usa en la clase, todos los métodos seguirán IEEE 754 y si se usa en el método, un método particular siga IEEE 754.

  • ¿Por qué se utiliza? ::: Como las diferentes plataformas tienen hardware de coma flotante diferente que calcula con más precisión y un mayor rango de valores que el que requiere la especificación de Java, lo que puede producir una salida diferente en diferentes plataformas. Por lo tanto, confirma la misma salida independientemente de la diferencia plataformas

  • strictlyfp también asegura aprovechar la velocidad y precisión de las operaciones de punto flotante de precisión extendida.

  • No hay desventaja con esta palabra clave que podemos usar cuando hacemos cálculos de coma flotante

  • Mi último punto es: ¿Qué es IEEE754 en resumen? IEEE 754 define el método estándar tanto para los cálculos de coma flotante como para el almacenamiento de valores de coma flotante, ya sea simple (32 bits, utilizado en flotantes Java) o doble (64 bits, utilizado en Java dobles) precisión. También define normas para cálculos intermedios y para formatos de precisión extendidos.


2

strictfpes una palabra clave y se puede usar como un modificador sin acceso para clases o métodos (pero nunca variables). Marcar una clase como strictfpsignifica que cualquier código de método en la clase se ajustará a las reglas estándar IEEE 754 para puntos flotantes.

Sin ese modificador, los puntos flotantes utilizados en los métodos podrían comportarse de una manera dependiente de la plataforma. Con él, puede predecir cómo se comportarán sus puntos flotantes independientemente de la plataforma subyacente en la que se esté ejecutando la JVM. La desventaja es que si la plataforma subyacente es capaz de soportar una mayor precisión, un strictfpmétodo no podrá aprovecharla.

Si no declara una clase como strictfp, aún puede obtener un strictfpcomportamiento método por método, declarando un método como strictfp.

~ Programador certificado SCJP Sun® para Java ™ 6 - Kathy Sierra y Bert Bates ~


0

El siguiente ejemplo de mayo puede ayudar a comprender esto más claramente: en Java, siempre que estemos usando buscando información precisa para cualquier operación, por ejemplo, si hacemos doble num1 = 10e + 102; doble num2 = 8e + 10; resultado = num1 + num2;

        The output will be so long and not precise, becasue it is precissed by the hardware e.g JVM and JIT has the license 
        as long as we dont have specify it Strictfp

Marking it Strictfp will make the result Uniform on every hardware and platform, because its precised value will be same
One scenario I can see is in a distributed application (or multiplayer game) where all floating-point calculations need to 
be deterministic no matter what the underlying hardware or CPU is.

0

La palabra clave 'strictlyfp' se usa para forzar la precisión de los cálculos de coma flotante (flotante o doble) en Java conforme al estándar 754 de IEEE, explícitamente. Si no utiliza la palabra clave estricta fp, la precisión del punto flotante depende del hardware de la plataforma de destino.

Si una interfaz o clase se declara con strictlyfp, entonces todos los métodos y tipos anidados dentro de esa interfaz o clase son implícitamente estrictosfp.

Enlace de referencia

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.