Pregunta

¿Por qué es obligatorio usar -ffast-math con g ++ para lograr la vectorización de bucles utilizando double¿s? No me gusta -ffast-math Porque no quiero perder precisión.

¿Fue útil?

Solución

No necesariamente pierdes precisión con -ffast-math. Solo afecta el manejo de NaN, Inf etc. y el orden en que se realizan las operaciones.

Si tiene un código específico en el que no desea que GCC reordene o simplifique los cálculos, puede marcar variables como utilizando un uso de un asm declaración.

Por ejemplo, el siguiente código realiza una operación de redondeo en f. Sin embargo, los dos f += g y f -= g Es probable que las operaciones sean optimizadas por GCC:

static double moo(double f, double g)                                      
{                                                                          
    g *= 4503599627370496.0; // 2 ** 52                                    
    f += g;                                                                
    f -= g;                                                                
    return f;                                                            
}                                                                     

En x86_64, puedes usar esto asm Declaración para instruir a GCC que no realice esa optimización:

static double moo(double f, double g)                                      
{                                                                          
    g *= 4503599627370496.0; // 2 ** 52                                    
    f += g;                                                                
    __asm__("" : "+x" (f));
    f -= g;
    return f;
}

Desafortunadamente, deberá adaptar esto para cada arquitectura. En PowerPC, usa +f en vez de +x.

Otros consejos

Muy probable porque la vectorización significa que puede tener resultados diferentes, o puede significar que pierde las señales/excepciones de puntos flotantes.

Si está compilando para 32 bits X86, entonces GCC y G ++ predeterminan el uso del X87 para las matemáticas de punto flotante, en 64 bits predeterminados a SSE, sin embargo, el X87 puede y producirá diferentes valores para el mismo cálculo, por lo que es poco probable G ++ G ++ considerará la vectorización si no puede garantizar que obtendrá los mismos resultados a menos que use -ffast-math o algunas de las banderas que enciende.

Básicamente se trata del entorno de punto flotante para el código vectorizado puede no ser el mismo que el de código no vectorizado, a veces de manera importante, si las diferencias no le importan, algo así como

-fno-math-errno -fno-trapping-math -fno-signaling-nans -fno-rounding-math

Pero primero busque esas opciones y asegúrese de que no afecten la corrección de su programa. -ffinite-math-only puede ayudar también

Porque -ffast-math habilitan operando reordenamiento lo que permite que muchos códigos se vectorizen.

Por ejemplo para calcular esto

sum = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + … a[99]

El compilador es requerido Para hacer las adiciones secuencialmente sin que -ffast-math, porque las matemáticas de punto flotante no son conmutadoras ni asociativas.

Esa es la misma razón Por qué los compiladores no pueden optimizar a*a*a*a*a*a a (a*a*a)*(a*a*a) sin que -ffast-math

Eso significa que no hay vectorización disponible a menos que tenga agregadas muy eficientes del vector horizontal.

Sin embargo, si -ffast-math está habilitado, la expresión se puede calcular como esto (Mirar A7. Auto-Vectorization)

sum0 = a[0] + a[4] + a[ 8] + … a[96]
sum1 = a[1] + a[5] + a[ 9] + … a[97]
sum2 = a[2] + a[6] + a[10] + … a[98]
sum3 = a[3] + a[7] + a[11] + … a[99]
sum’ = sum0 + sum1 + sum2 + sum3

Ahora el compilador puede vectorizarlo fácilmente agregando cada columna en paralelo y luego hacer una suma horizontal al final

Lo hace sum’ == sum? Sólo si (a[0]+a[4]+…) + (a[1]+a[5]+…) + (a[2]+a[6]+…) + ([a[3]+a[7]+…) == a[0] + a[1] + a[2] + … Esto se mantiene bajo asociatividad, que los flotadores no se adhieren, todo el tiempo. Especificación /fp:fast Deje que el compilador transforme su código para que se ejecute más rápido, hasta 4 veces más rápido, para este cálculo simple.

¿Prefieres rápido o preciso? - A7. Vectorización automática

Puede ser habilitado por el -fassociative-math bandera en GCC

Lecturas adicionales

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top