Existen muchos desafíos técnicos que hacen que la reproducibilidad exacta bit por bit de los resultados computacionales sea extremadamente difícil de lograr.
A nivel de software, los cambios en el código o en cualquiera de las bibliotecas utilizadas por el código obviamente pueden causar resultados diferentes. Te sorprendería la cantidad de bibliotecas de soporte que pueden terminar vinculadas a un código científico típico.
En un nivel inferior, recompilar cualquiera de los códigos o cualquiera de las bibliotecas utilizadas por el código con un nuevo compilador o con diferentes optimizaciones de compilador activadas también puede causar problemas. Una razón es que varias operaciones en el código pueden realizarse en un orden diferente cuando se vuelve a compilar el código. Como la adición de coma flotante no es asociativa (a + b) + c <> a + (b + c), esto puede dar resultados diferentes.
Bien, ¿y si conservamos todo el entorno de software (SO, bibliotecas y código compilado) (p. Ej.) Grabándolo en un CD-Rom de arranque que ejecutará el código. Ahora, ¿podemos estar seguros de que obtendremos los mismos resultados si ejecutamos este código en una computadora diferente?
Sorprendentemente, algunos códigos realmente varían el orden de los cálculos en función de los aspectos del modelo de procesador particular en el que se están ejecutando. Por ejemplo, las bibliotecas de álgebra lineal optimizadas suelen dividir las multiplicaciones de matrices para trabajar en bloques que se adaptarán a la memoria caché. Cuando Intel lanza un nuevo microprocesador con una memoria caché más grande, el código puede ajustar dinámicamente el tamaño del bloque, lo que resulta en una aritmética que se realiza en un orden diferente y da resultados diferentes. Otros códigos ajustan dinámicamente el orden de los cálculos en función de la cantidad de memoria disponible, si ejecuta el código en una computadora con más memoria que bien podría hacer que la aritmética se realice en un orden diferente y, por lo tanto, arroje resultados diferentes.
Las cosas se vuelven increíblemente más complicadas cuando agregas código multiproceso, ya que el historial de ejecución exacto de los diferentes hilos a menudo no es determinista y esto puede hacer que las operaciones aritméticas se realicen en un orden diferente de una ejecución a la siguiente.
En la práctica, lo máximo que realmente puede esperar son resultados similares de una máquina a otra, hasta las tolerancias de precisión de los algoritmos utilizados. por ejemplo, si tengo un problema de búsqueda de raíz y uso la bisección para obtener una raíz dentro de + -1.0e-10, entonces debería estar contento siempre que diferentes máquinas produzcan respuestas que estén de acuerdo con esa tolerancia.