performance math gcc floating-point fast-math

performance - ¿Qué hace realmente la última matemática de gcc?



math floating-point (2)

Como mencionó, permite optimizaciones que no conservan el estricto cumplimiento de IEEE.

Un ejemplo es esto:

x = x*x*x*x*x*x*x*x;

a

x *= x; x *= x; x *= x;

Debido a que la aritmética de punto flotante no es asociativa, el orden y la factorización de las operaciones afectarán los resultados debido al redondeo. Por lo tanto, esta optimización no se realiza bajo un comportamiento estricto de FP.

EDITAR: Realmente no he comprobado para ver si GCC realmente hace esta optimización particular. Pero la idea es la misma.

Entiendo que la bandera gcc''s --ffast-math puede aumentar en gran medida la velocidad de las operaciones flotantes, y va más --ffast-math estándares IEEE, pero parece que no puedo encontrar información sobre lo que realmente está sucediendo cuando está encendido. ¿Puede alguien explicar algunos detalles y quizás dar un ejemplo claro de cómo algo cambiaría si la bandera estuviera encendida o apagada?

Intenté profundizar en SO para preguntas similares, pero no pude encontrar nada que explicara el funcionamiento de ffast-math.


-ffast-math hace mucho más que romper el estricto cumplimiento IEEE.

En primer lugar, por supuesto, rompe la estricta conformidad IEEE, permitiendo, por ejemplo, el reordenamiento de las instrucciones a algo que es matemáticamente el mismo (idealmente) pero no exactamente el mismo en coma flotante.

En segundo lugar, desactiva la configuración de errno después de las funciones matemáticas de instrucción única, lo que significa evitar una escritura en una variable local de subproceso (esto puede hacer una diferencia del 100% para esas funciones en algunas arquitecturas).

En tercer lugar, supone que todas las matemáticas son finitas , lo que significa que no se realizan controles para NaN (o cero) donde tendrían efectos perjudiciales. Simplemente se supone que esto no va a suceder.

En cuarto lugar, permite aproximaciones recíprocas para la división y la raíz cuadrada recíproca.

Además, desactiva el cero firmado (el código asume que el cero firmado no existe, incluso si el destino lo admite) y el cálculo matemático de redondeo, que permite, entre otras cosas, el plegado constante en tiempo de compilación.

Por último, genera código que supone que no pueden producirse interrupciones de hardware debido a la matemática de señalización / captura (es decir, si no se pueden deshabilitar en la arquitectura de destino y, en consecuencia , suceden , no se manejarán).