jueves, agosto 20, 2009

Del como prevenir un error de coma flotante y del como un issue pasó por SAP, Intel y Microsoft

Meses atrás me informaron de un dump que le ocurrió a una usuaria mientras trabajaba con la transacción SAP que diseñamos para el manejo de modelos econométricos.

El problema se presentaba al momento de calcular un antilogaritmo para un número con exponente muy pequeño, por ejemplo: 10^-900 lo cual normalmente cualquier mortal lo entendería como un valor positivo muy cercano a cero, pero bueno, SAP no.

En el análisis de errores para ese dump, SAP nos indicaba lo siguiente:

There may be an overflow or an underflow.
With the floating point format defined according to IEEE 754 and widely used on workstations, the following must apply for "x **y": -709 < y * ln x < 710


A lo cual nosotros procedimos a implementar la fórmula tal como venía entregada sin mayor análisis ni revisión.

Tiempo después volvió a ocurrir el mismo error al intentar calcular 10^-307.655 a lo cual aplicamos la regla de SAP teniendo lo siguiente
y * ln x = -307.55 * ln 10 = -708.4018168
-709 < y * ln x < 710 = VERDADERO
al satisfacerse la regla y decidimos consultar a SAP sobre que estaba pasando y por qué se daba tal error si se estaba cumpliendo la regla establecida.

Parte del mensaje y algunos errores adicionales pueden ser verificados aquí.

El issue fue inicialmente tratado por SAP quien recomendó que aplicáramos un redondeo antes del cálculo, esto bajo una idea errada que el número internamente se almacenaba en un formato tal como -3.07549999999999999E+02 lo cual se implementó pero no sirvió de nada.

Al cabo de un tiempo me enteré que el tema lo veía Microsoft (imagino por un vínculo al Sistema Operativo) quien me indicó que se trataba de un problema de trabajar con un resultado del tipo número subnormal (denormal number) el cual al trabajarse en un procesador Itanium, de acuerdo a Intel, se realizaba 100 veces más lento que con un número de coma flotante normalizado y que existía la opción de que automáticamente Itanium lo volviera cero lo cual es más rápido aún cuando se pierde precisión.

Me indicaron que se iba a presentar el caso a Microsoft ya que a la fecha ningún compilador Microsoft tenía la capacidad de hacer esa conversión automática en procesadores Itanium.

Aún cuando el problema a la fecha sigue estancado ya que siguen buscando a alguien que conozca sobre Itanium, decidí enfocarme en el problema inicial que tenía ya que aún con todo lo que me indicaba tenía pensado que una buena validación podría prevenir el error (y que la actual de SAP no lo permitía).

Afortunadamente Jason Kafka tuvo a bien revisar la regla que SAP provee y luego nutrirme de cierta teoría que involucra al estándar IEEE 754 para aritmética de coma flotante. Y que establece los límites para cada caso dependiendo el número de bits; en este caso Itanium trabaja con 64 bits.

Para este caso el exponente más alto y más bajo con representación disponible son 1023 y -1022 respectivamente (si la base es 2).

Luego decidí hacer gala de mis antiguos conocimientos de matemáticas y planteé lo siguiente:

2^-1022 <= x^y <= 2^1023

aplicando logaritmo natural/neperiano a cada miembro de la expresión...
-1022 * ln(2) <= y * ln(x) <= 1023 * ln(2)

lo cual resulta aproximadamente en:
-708.3964185 <= y * ln(x) <= 709.0895657

Es decir la regla que daba SAP era aproximada y era la causa de todos los males, en este caso lo único que se tenía que hacer era colocar las cotas adecuadas y así prevenir el dump.


En este momento SAP, Microsoft e Intel siguen trabajando en este tema, por mi lado creo ya tenerlo (si no solucionado) al menos controlado.

Sin embargo descuido mío fue el no verificar las cotas máximas o el no relacionar inmediatamente el por qué del componente central de la desigualdad "y * ln(x)", pues al parecer con el mismo razonamiento anterior es como SAP llegó a la conclusión de la regla (aproximada) de desigualdad que si bien falla en los casos extremos, contempla un amplio rango de casos, tal como lo manifestó el consultor alemán de Plataformas de Desarrollo Microsoft.

No hay comentarios.: