2010-01-27 14 views
10

Me gustaría saber si puedo asumir que las mismas operaciones en los mismos números de coma flotante de 64 bits dan exactamente los mismos resultados en cualquier PC moderna y en la mayoría de los lenguajes de programación comunes. (C++, Java, C#, etc.). Podemos suponer que estamos operando con números y que el resultado es también un número (sin NaN, INF, etc.).¿Los números de punto flotante de 64 bits se comportan de manera idéntica en todas las PC modernas?

Sé que hay dos estándares de computación muy similares que usan números de coma flotante (IEEE 854-1987 e IEEE 754-2008). Sin embargo, no sé cómo es en la práctica.

Respuesta

8

modernos que implementan de 64 bits en coma flotante suele poner en práctica algo que está cerca del estándar IEEE 754-1985, recientemente sustituida por la norma 754-2008.

La norma 754 especifica el resultado que debe obtener de ciertas operaciones básicas, especialmente suma, resta, multiplicación, división, raíz cuadrada y negación. En la mayoría de los casos, el resultado numérico se especifica con precisión: el resultado debe ser el número representable más cercano al resultado matemático exacto en la dirección especificada por el modo de redondeo (al más cercano, hacia el infinito, hacia cero o hacia el infinito negativo). En el modo "al más cercano", el estándar también especifica cómo se rompen los vínculos.

Debido a esto, las operaciones que no involucran condiciones de excepción como desbordamiento obtendrán los mismos resultados en diferentes procesadores que cumplan con la norma.

Sin embargo, existen varios problemas que interfieren con la obtención de resultados idénticos en diferentes procesadores. Una de ellas es que el compilador a menudo es libre de implementar secuencias de operaciones de punto flotante en una variedad de formas. Por ejemplo, si escribe "a = b c + d" en C, donde todas las variables se declaran dobles, el compilador puede calcular "b c" en aritmética de precisión doble o algo con más rango o precisión. Si, por ejemplo, el procesador tiene registros capaces de mantener números de coma flotante de precisión extendida y realizar operaciones aritméticas con precisión extendida no requiere más tiempo de CPU que la aritmética con precisión doble, es probable que un compilador genere código utilizando extensiones extendidas. -precisión. En un procesador de este tipo, es posible que no obtenga los mismos resultados que en otro procesador. Incluso si el compilador hace esto regularmente, puede que no en algunas circunstancias porque los registros están llenos durante una secuencia complicada, por lo que almacena temporalmente los resultados intermedios en la memoria. Cuando hace eso, puede escribir solo el doble de 64 bits en lugar del número de precisión extendida. Por lo tanto, una rutina que contenga aritmética de punto flotante podría dar resultados diferentes solo porque se compiló con código diferente, tal vez en línea en un lugar, y el compilador necesitaba registros para otra cosa.

Algunos procesadores tienen instrucciones para calcular una multiplicación y una adición en una instrucción, por lo que "b c + d" puede ser calculada sin ninguna aproximación intermedia y obtener un resultado más preciso que en un procesador que primero calcula b c y luego agrega d.

Su compilador puede tener interruptores para controlar el comportamiento de esta manera.

Hay algunos lugares donde el estándar 754-1985 no requiere un resultado único. Por ejemplo, al determinar si se ha producido subdesbordamiento (un resultado es demasiado pequeño para representarse con precisión), el estándar permite que una implementación realice la determinación antes o después de redondear el significado (los bits de fracción) a la precisión del objetivo. Por lo tanto, algunas implementaciones le dirán que ha ocurrido desbordamiento cuando otras implementaciones no lo harán.

Una característica común en los procesadores es tener un modo "casi IEEE 754" que elimina la dificultad de tratar con subdesbordamiento sustituyendo cero en lugar de devolver el número muy pequeño que requiere el estándar. Naturalmente, obtendrá diferentes números al ejecutar en un modo tal que cuando se ejecuta en el modo más compatible. El modo no conforme puede ser el predeterminado establecido por su compilador y/o sistema operativo, por razones de rendimiento.

Tenga en cuenta que una implementación IEEE 754 generalmente no se proporciona solo por hardware sino por una combinación de hardware y software. El procesador puede hacer la mayor parte del trabajo, pero depende del software para manejar ciertas excepciones, establecer ciertos modos, etc.

Cuando se mueve más allá de las operaciones aritméticas básicas a cosas como seno y coseno, usted es muy dependiente de la biblioteca que utiliza. Las funciones trascendentales generalmente se calculan con aproximaciones cuidadosamente diseñadas. Las implementaciones son desarrolladas independientemente por varios ingenieros y obtienen resultados diferentes entre sí. En un sistema, la función sin puede dar resultados precisos dentro de una ULP (unidad de menor precisión) para argumentos pequeños (menos de pi o más) pero errores más grandes para argumentos grandes. En otro sistema, la función pecado puede dar resultados precisos dentro de varios ULP para todos los argumentos. No se sabe que ninguna biblioteca matemática actual produzca resultados redondeados correctamente para todas las entradas. Existe un proyecto, crlibm (Correctly Rounded Libm), que ha realizado un buen trabajo para alcanzar este objetivo, y han desarrollado implementaciones para partes significativas de la biblioteca matemática que se redondean correctamente y tienen un buen rendimiento, pero no toda la biblioteca matemática. todavía.

En resumen, si tiene un conjunto manejable de cálculos, comprenda la implementación de su compilador, y tenga mucho cuidado, puede confiar en resultados idénticos en diferentes procesadores. De lo contrario, obtener resultados completamente idénticos no es algo en lo que pueda confiar.

+0

Todos los puntos buenos. Por ejemplo, de hardware que ofrece resultados diferentes, x86_64 (es decir, todos los procesadores de clase Intel Pentium) ofrece resultados diferentes a los de k1om (es decir, Intel Phi, también conocido como Intel MIC). Los registros internos son de diferentes tamaños, aunque la representación de la memoria externa de 64 bits (IEEE 754) sea la misma. –

2

Las FPU modernas implementan flotadores IEEE754 en formatos simples y dobles, y algunos en formato extendido. Se admite un cierto conjunto de operaciones (casi cualquier cosa en math.h), con algunas instrucciones especiales flotando por ahí.

+0

Es cierto, pero ¿qué garantías tiene IEEE para la reproducibilidad? – ergosys

+0

Ninguno, como se mostró el error Intel FDIV. –

1

asumiendo que está hablando de aplicar operaciones múltiples, no creo que obtendrá los números exactos. La arquitectura de la CPU, el uso del compilador, la configuración de optimización cambiarán los resultados de sus cálculos.

si quiere decir el orden exacto de las operaciones (en el nivel de ensamblaje), creo que todavía obtendrá variaciones. Por ejemplo, los chips Intel usan internamente la precisión extendida (80 bits), que puede no ser el caso para otras CPU. (No creo que se requiera una precisión extendida)

0

Para el tipo de datos de 64 bits, solo sé de "double precision"/"binary64" del IEEE 754 (1985 y 2008 no difieren mucho aquí para los casos comunes) que se utilizan.

Nota: Los tipos de radix definidos en IEEE 854-1987 son reemplazados por IEEE 754-2008 de todos modos.

1

El mismo programa C# puede mostrar diferentes resultados numéricos en la misma PC, una vez compilado en modo de depuración sin optimización, compilado por segunda vez en modo de lanzamiento con la optimización habilitada. Esa es mi experiencia personal No lo consideramos cuando creamos un conjunto de pruebas de regresión automática para uno de nuestros programas por primera vez, y nos sorprendió por completo que muchas de nuestras pruebas fallaran sin ninguna razón aparente.

7

Si quiere decir obtener exactamente el mismo resultado, entonces la respuesta es no.

Incluso podría obtener resultados diferentes para compilaciones de depuración (no optimizadas) frente a versiones (optimizadas) en la misma máquina en algunos casos, por lo que ni siquiera suponga que los resultados pueden ser siempre idénticos en máquinas diferentes.

(Esto puede suceder, por ejemplo, en una computadora con procesador Intel, si el optimizador mantiene una variable para un resultado intermedio en un registro, que se almacena en la memoria en la versión no optimizada. Como los registros Intel FPU son de 80 bits, las variables dobles son de 64 bits, el resultado intermedio se almacenará con mayor precisión en la construcción optimizada, causando valores diferentes en los resultados posteriores).

En la práctica, sin embargo, a menudo puede obtener los mismos resultados, pero no debe confiar en ello.

1

Para C# en x86, se utilizan registros FP de 80 bits.

El estándar C# dice que el procesador debe operar con la misma precisión que el propio tipo (es decir, 64 bits en el caso de un "doble"). Las promociones están permitidas, excepto para el almacenamiento. Eso significa que los locales y los parámetros podrían tener una precisión superior a 64 bits.

En otras palabras, la asignación de una variable miembro a una variable local podría (y de hecho lo hará en determinadas circunstancias) ser suficiente para dar una desigualdad.

Consulte también: procesadores Float/double precision in debug/release modes

Cuestiones relacionadas