🧮 Computational Mathematics

Inicio · Parte 01 — Aritmética computacional y representación numérica

039 — Reproducibilidad numérica entre plataformas

basico-computacional clase 19 de 20 4 horas demostración reproducibility

La suma en punto flotante no es asociativa; reproducir un resultado exige fijar el orden de las operaciones.

Fórmulas

(a + b) + c ≠ a + (b + c)  en float64
la suma es conmutativa pero no asociativa

Desarrollo

En los reales, la suma es asociativa: agrupar de una forma u otra da el mismo resultado. En punto flotante no lo es, porque cada suma parcial se redondea y el redondeo depende de las magnitudes involucradas. El ejemplo clásico usa 1e16, 1.0 y −1e16: sumando de izquierda a derecha, el 1.0 se pierde por estar bajo el ULP de 1e16; sumando en otro orden, sobrevive.

Esto tiene una consecuencia incómoda para la reproducibilidad: fijar la semilla aleatoria no basta. Dos ejecuciones del mismo código pueden dar resultados distintos si el orden de las sumas cambia, y el orden cambia con el número de hilos, la arquitectura de la GPU, la versión de la biblioteca BLAS o incluso la disponibilidad de instrucciones vectoriales.

Por eso los frameworks de deep learning ofrecen modos deterministas explícitos (torch.use_deterministic_algorithms(True)), que fuerzan implementaciones con orden fijo a costa de rendimiento. Sin ese modo, el mismo entrenamiento con la misma semilla puede divergir tras unos miles de pasos —no porque haya aleatoriedad extra, sino porque las diferencias de redondeo se amplifican.

El programa adopta la consecuencia como norma: todas las demostraciones son deterministas en un solo hilo y con orden de operaciones fijo, y un test comprueba que dos ejecuciones devuelven exactamente el mismo diccionario. Esa comprobación sería imposible de garantizar en cálculo paralelo sin medidas adicionales.

Ejemplo trabajado

El mismo conjunto de sumandos en dos órdenes.

valores = [1e16, 1.0, −1e16, 1.0]

De izquierda a derecha:
  1e16 + 1.0    = 1e16        ← el 1.0 cae bajo el ULP
  1e16 − 1e16   = 0.0
  0.0 + 1.0     = 1.0         resultado: 1.0

De derecha a izquierda:
  1.0 − 1e16    = −1e16
  −1e16 + 1.0   = −1e16
  −1e16 + 1e16  = 0.0         resultado: 0.0

math.fsum(valores) = 2.0      ← el valor exacto

¿Asociativa en ℝ?      Sí
¿Asociativa en float64? No

Qué calcula el laboratorio

El orden de la suma cambia el resultado en punto flotante.

python classes/part-01-aritmetica-computacional-y-representacion-numerica/039-reproducibilidad-numerica-entre-plataformas/lab.py
compmath run 039

Salidas del laboratorio (7)

Muestra de la ejecución real

{
  "valores": [
    1e+16,
    1.0,
    -1e+16,
    1.0
  ],
  "suma_de_izquierda_a_derecha": 1.0,
  "suma_de_derecha_a_izquierda": 0.0,
  "coinciden": false,
  "suma_compensada": 2.0,
  "suma_es_asociativa_en_R": true
}

Errores comunes

Dónde se usa

Reproducibilidad de experimentos, comparación de implementaciones, depuración de divergencias entre entornos y publicación de resultados verificables. Es la razón por la que los papers serios publican semilla, versión y hardware.

Idea rectora de la parte

La cancelación catastrófica destruye dígitos significativos sin lanzar excepciones.

Error a evitar

Comparar floats con `==` en lugar de una tolerancia razonada.

Conexión con IA

float32, bfloat16 y la cuantización a int8 son decisiones de representación. Los NaN en un entrenamiento casi siempre nacen aquí, no en la arquitectura.

Bibliografía de la clase

Archivos de la clase