8

Estoy escribiendo software numérico en tiempo real, en C++, compilándolo actualmente con Visual-C++ 2008. Ahora usando el modelo de punto flotante 'rápido' (/fp:fast), varias optimizaciones , la mayoría de ellos de utilidad mi caso, pero en concreto:Opciones de compilador de punto flotante de C++ | Prevenir a/b -> a * (1/b)

a/b -> a*(1/b) Division by multiplicative inverse 

numéricamente es demasiado inestable para una gran cantidad de mis cálculos.

(ver: Microsoft Visual C++ Floating-Point Optimization)

El cambio a /fp:precise hace que mi aplicación se ejecute más de dos veces más lento. ¿Es posible afinar el optimizador (es decir, desactivar esta optimización específica) o, de algún modo, omitirlo manualmente?

- -código mínimo Actual ejemplo: -

[algoritmos mi código real se relaciona principalmente con matriz]
void test(float a, float b, float c, 
    float &ret0, float &ret1) { 
    ret0 = b/a; 
    ret1 = c/a; 
} 

de salida: VC (cl, versión 15, 0x86) es:

divss  xmm0,xmm1 
mulss  xmm2,xmm0 
mulss  xmm1,xmm0 

Tener un div, en lugar de dos es un gran problema numéricamente, (xmm0, está precargado con 1.0f de RAM), dependiendo de los valores de xmm1,2 (que puede estar en diferentes r anges) puede perder mucha precisión (compilando sin SSE, emite un código stack-x87-FPU similar).

Envolver la función con

#pragma float_control(precise, on, push) 
... 
#pragma float_control(pop) 

resuelve el problema de la precisión, pero en primer lugar, que sólo está disponible en un nivel de función (global-scope), y en segundo lugar, que impide la expansión en línea de la función, (es decir, , sanciones de velocidad son demasiado altos)

salida 'exacta' está siendo echados a 'doble' de ida y vuelta como, bueno:

divsd  xmm1,xmm2 
cvtsd2ss xmm1,xmm1 
divsd  xmm1,xmm0 
cvtpd2ps xmm0,xmm1 
+2

Cualquier matemática de punto flotante que dependa de la igualdad será inestable. –

+1

@Hans: OP no busca la igualdad; él/ella está diciendo que el compilador está haciendo la sustitución anterior como una optimización, y que esto no es útil en su aplicación. –

+0

@Oli: aún no sabemos si los requisitos de precisión de OP son alcanzables o están fuera de este mundo. – peterchen

Respuesta

0

solución (extraño) que he encontrado: siempre dividiendo por el mismo valor en una función - añadir un poco de épsilon:

a/b; c/b 

->

a/(b+esp1); c/(b+esp2) 

también le ahorra de la div de vez en cuando por cero

2

Este documento declara que se puede controlar el las optimizaciones de flotación-señalamiento línea por línea usando pragmas.

0

¿Puede poner las funciones que contienen esos cálculos en un archivo de código fuente separada y compilar solamente ese archivo con los diferentes ajustes?

No sé si eso es seguro sin embargo, usted tendrá que comprobar!

3

Añadir la

#pragma float_control(precise, on)

antes de la computación y

#pragma float_control(precise,off)

después de eso. Creo que debería hacerlo.

+0

sí, eso es lo que estoy usando actualmente: float_control #pragma (precisa, puesto, introduzca) ... float_control #pragma (pop) por desgracia, parece que funciona sólo en un nivel completamente funciones, además de prevenir la alineación. Agregaré un comentario con mis hallazgos actuales. Realmente sería rockero, si hubiera una opción de optimización de flotación más ajustada – oyd11

1

También hay __assume. Puedes usar __assume (a/b! = (A * (1/b))). Nunca he usado __assume, pero en teoría existe exactamente para ajustar el optimizador.

+0

Es bueno saber sobre __assume(), otros compiladores que he usado anteriormente tenían opciones similares (NASSERT en los compiladores de TI), intentarán eso, sin embargo , Creo que el compilador ya supone (a/b! = (A * (1/b))) – oyd11

Cuestiones relacionadas