5

Estoy desarrollando una aplicación C que necesita determinismo de coma flotante. También me gustaría que las operaciones de punto flotante sean bastante rápidas. Esto incluye funciones trascendentales estándar no especificadas por IEEE754 como seno y logaritmo. Las implementaciones de punto flotante de software que he considerado son relativamente lentas, en comparación con el punto flotante de hardware, por lo que estoy considerando simplemente redondear uno o dos de los bits menos significativos de cada respuesta. La pérdida de precisión es un compromiso adecuado para mi aplicación, pero ¿será suficiente para garantizar resultados deterministas en todas las plataformas? Todos los valores de coma flotante serán dobles.¿Puedo usar el redondeo para garantizar el determinismo de las operaciones de punto flotante atómico?

Me doy cuenta de que el orden de las operaciones es otra fuente potencial de variación en los resultados de coma flotante. Tengo una forma de abordar eso ya.

Sería excelente si hubiera implementaciones de software de las principales implementaciones de hardware de coma flotante en uso hoy en día, por lo que podría probar una hipótesis como esta directamente.

+4

mayoría de los compiladores hoy en día tienen algún tipo de opción estricta-FP. Eso probablemente haga lo que quieras. – Mysticial

+0

IEE-754 ya tiene reglas para el redondeo, por lo que es poco probable que las reglas que aplique sobre ellas mejoren las cosas. ¿Puede ser más específico sobre lo que quiere decir con "resultados deterministas"? –

+0

@Mark El mismo código dará resultados diferentes en hardware diferente para código de punto flotante. Imagino que eso es lo que significa * determinista *. –

Respuesta

2

Según tengo entendido, tiene una implementación de software de una función trascendental como sin (x), expresada en términos de operaciones estándar IEEE como coma flotante añadir y multiplicar, y quiere asegurarse de obtener la misma respuesta en todas las máquinas (o, al menos, todas las máquinas que te interesan).

En primer lugar, entiende: esto no será portátil para todas las máquinas. P.ej. El punto flotante del mainframe de IBM no es IEEE, y no dará las mismas respuestas. Para obtener eso exactamente, necesitaría tener una implementación de software de las operaciones estándar de IEEEE como FP add y multiply.

Supongo que solo le interesan las máquinas que implementan el punto flotante estándar IEEE. Y también estoy adivinando que no te preocupan los NaN, ya que los NaN no estaban completamente estandarizados por IEEE 754-1985, y surgieron dos implementaciones opuestas: HP y MIPS, vedrsus casi todos los demás. 1

Con esas restricciones, ¿cómo puede obtener variabilidad en sus cálculos?

(1) Si el código se está paralelizando. Asegúrate de que eso no esté sucediendo. (Es poco probable, pero algunas máquinas podrían). La paralelización es una fuente importante de variación de resultados en FP. Al menos una compañía que conozco, que se preocupa por la reproducibilidad y el paralelismo, se niega a usar FP y solo usa números enteros.

(2) Asegúrese de que la máquina esté configurada correctamente.

E.g. la mayoría de las máquinas calculan en 32 o 64 bits de precisión (C estándar original era 64 bit "doble" en todas partes. Pero Intel x86/x87 puede calcular en 80 bit en registros, y redondear a 64 o 32 al derramar. 1 muestra cómo cambiar el x86/x87 control de precisión de 80 a 64 bits, utilizando el ensamblaje en línea. Tenga en cuenta que este código es a nivel de ensamblaje y no portátil, pero la mayoría de las otras máquinas ya hacen cálculos con 32 o 64 bits de precisión, y no necesita preocuparse por el x87 80 bit.

(Por cierto, en x86 usted solo puede evitar todos los problemas usando SSE FP; el viejo legacy Intel x87 FP nunca puede dar exactamente las mismas respuestas (aunque si establece el control de precisión (PC) a 64 bits en lugar de a 80 bits, obtendrá los mismos resultados, excepto si hubo un desbordamiento intermedio, ya que el ancho del exponente no se ve afectado, solo la mantisa))

P. ej. asegúrese de estar utilizando el mismo modo de flujo insuficiente en todas las máquinas. Es decir. asegúrese de que denomers o habilitado, o de manera opuesta que todas las máquinas están al ras en modo cero. Aquí está la elección de Dobson: los modos de descarga a cero no están estandarizados, pero algunas máquinas, p. GPU, simplemente no han tenido números desnormalizados. Es decir.muchas máquinas tienen FORMATOS de número estándar IEEE, pero no una aritmética estándar IEEE real (con densidades). Mi druther es para exigir IEEE denorms, pero si fuera absolutamente paranoico me iría con la descarga a cero, y obligar a que me limpie en el software.

(3) Asegúrese de estar utilizando las mismas funciones de idioma. Los programas antiguos de C hacen todos los cálculos en "doble" (64 bits), pero ahora se permite calcular en precisión simple. Lo que sea, quieres hacerlo de la misma manera en todas las máquinas.

(4) Algunos artículos más pequeños WRT su código:

evitar grandes expresiones que un compilador es probable que reorganizar (si no implementa estricto FP bien los conmutadores)

posible escribir todo el código en forma simple como

double a = ...; 
double b = ...; 
double c = a *b; 
double d = ...; 
double e = a*d; 
double f = c + e; 

en lugar de

f = (a*b) + (a*c); 

que podría ser optimizado para

f = a*(b+c); 

Voy a dejar de hablar de las opciones del compilador para el último, porque es más largo.

Si hace todo esto, entonces sus cálculos deben ser absolutamente repetibles. El punto flotante IEEE es exacto, siempre da las mismas respuestas. Es la reorganización de los cálculos por parte del compilador en el camino al IEEE FP que introduce la variabilidad.

No debería ser necesario redondear bits de orden baja. Pero hacerlo también no va a doler, y puede enmascarar algunos problemas. Recuerde: es posible que necesite enmascarar al menos un bit por cada agregado ....

(2) Optimizaciones del compilador reorganizando el código de diferentes maneras en diferentes máquinas. Como dijo un comentador, use lo que sea que su compilador cambie para un FP estricto.

Es posible que tenga que deshabilitar toda la optimización para el archivo que contiene su código de pecado.

Es posible que tenga que usar volátiles.

Afortunadamente, existen modificadores de compilación más específicos. P.ej. para gcc:

-ffp-contract = off --- deshabilita la función de multiplicación fusionada, ya que no todas sus máquinas de destino pueden tenerlas.

-fexcess precisión estándar = --- desactiva cosas como Intel x86/x87 exceso de precisión en los registros internos

-std = c99 --- especifica bastante estricta norma lenguaje C. Por desgracia no se han aplicado por completo, ya que google hoy

asegurarse de que no tiene optimizaciones habilitadas como -funsafe-matemáticas y -fassociativbe-matemáticas

+0

No puedo creer que haya escrito todo lo anterior, y olvide mencionar: los superacumuladores son una forma realmente genial de proporcionar cálculos de "coma flotante" poco precisos. Cito "fp", porque los superacumuladores en realidad no son coma flotante; en realidad son valores de punto fijo enteros GRANDES. Los menciono en http://semipublic.comp-arch.net/wiki/Superaccumulator, con consejos para algunos de los artículos clásicos. –

Cuestiones relacionadas