Tengo un modelo considerable (~ 5000 líneas) escrito en C. Es un programa en serie, sin generación de números aleatorios en ninguna parte. Utiliza la biblioteca FFTW para funciones que usan FFT: no conozco los detalles de la implementación de FFTW, pero supongo que las funciones allí también son deterministas (corríjame si estoy en error).
El problema que no puedo entender es que obtengo pequeñas diferencias en los resultados para ejecuciones idénticas en la misma máquina (mismo compilador, mismas bibliotecas).
Utilizo variables de doble precisión, y para generar el resultado en una variable, value
por ejemplo, emito:
fprintf(outFID, "%.15e\n", value);
o
fwrite(&value, 1, sizeof(double), outFID);
Y constantemente obtendría diferencias como:
2.07843469652206 4 e-16 vs. 2.07843469652206 3 e-16
He pasado mucho tiempo tratando de entender por qué es esto. Inicialmente pensé que uno de mis chips de memoria se había estropeado, y los ordené y los reemplacé, sin éxito. Posteriormente también intenté ejecutar mi código en la máquina Linux de un colega, y obtengo diferencias de la misma naturaleza.
¿Qué podría estar causando esto? Es un problema pequeño ahora, pero me pregunto si es la "punta del iceberg" (de un problema grave).
Pensé que publicaría aquí en lugar de StackOverflow en caso de que alguien que trabajara con modelos numéricos pudiera haber encontrado este problema. Si alguien puede arrojar luz sobre esto, estaría muy agradecido.
Seguimiento de comentarios:
Christian Clason y Vikram: primero, gracias por su atención a mi pregunta. Los artículos que vinculó sugieren que: 1. los errores de redondeo limitan la precisión, y 2. códigos diferentes (como la introducción de declaraciones de impresión aparentemente inofensivas) pueden afectar los resultados hasta la máquina epsilon. Debo aclarar que no estoy comparando los efectos fwrite
y fprintf
funciones. Estoy usando uno o el otro. En particular, se utiliza el mismo ejecutable para ambas ejecuciones. Simplemente estoy afirmando que el problema ocurre si uso fprintf
OR fwrite
.
Entonces, la ruta del código (y el ejecutable) es la misma, y el hardware es el mismo. Con todos estos factores externos mantenidos constantes, ¿de dónde proviene fundamentalmente la aleatoriedad? Sospeché que el cambio de bit ocurrió debido a que la memoria defectuosa no retiene un bit correctamente, es por eso que reemplacé los chips de memoria, pero ese no parece ser el problema aquí, verifiqué e indicó. Mi programa genera miles de estos números de doble precisión en una sola ejecución, y siempre hay un puñado aleatorio que tiene volteos de bits aleatorios.
Seguimiento del primer comentario de Christian Clason: ¿Por qué lo mismo que 0 dentro de la precisión de la máquina? El número positivo más pequeño para un doble es 2.22e-308, entonces ¿no debería ser igual a 0? Mi programa genera miles de valores en el rango de 10 ^ -16 (que van desde 1e-15 a 8e-17) y hemos estado viendo variaciones significativas en nuestro proyecto de investigación, así que espero que no hayamos estado mirando sin sentido números.
Seguimiento n. ° 2 :
Esta es una gráfica de la serie de tiempo producida por el modelo, para ayudar en la discusión derivada en los comentarios.