FMA3 en GCC: cómo habilitar

Tengo un i5-4250U que tiene AVX2 y FMA3. Estoy probando un código de multiplicación de matriz densa en GCC 4.8.1 en Linux que escribí. A continuación hay una lista de tres formas diferentes que compilo.

SSE2:     gcc matrix.cpp -o matrix_gcc -O3 -msse2 -fopenmp
AVX:      gcc matrix.cpp -o matrix_gcc -O3 -mavx  -fopenmp
AVX2+FMA: gcc matrix.cpp -o matrix_gcc -O3 -march=native -fopenmp -ffast-math

Las versiones SSE2 y AVX son claramente diferentes en rendimiento. Sin embargo, el AVX2 + FMA no es mejor que la versión AVX. No entiendo esto Obtengo más del 80% de los fracasos máximos de la CPU suponiendo que no hay FMA pero creo que debería poder hacerlo mucho mejor con FMA. La multiplicación de matrices debe beneficiarse directamente de FMA. Básicamente estoy haciendo productos de ocho puntos a la vez en AVX. Cuando compruebomarch=native da:

cc -march=native -E -v - </dev/null 2>&1 | grep cc1 | grep fma 
...-march=core-avx2 -mavx -mavx2 -mfma -mno-fma4 -msse4.2 -msse4.1 ...

Así que puedo ver que está habilitado (solo para estar seguro de que agregué-mfma pero no hace diferencia).ffast-math debe permitir un modelo de punto flotante relajadoCómo usar las instrucciones Fused Multiply-Add (FMA) con SSE / AVX

Editar:

Basándome en los comentarios de Mysticial, seguí adelante y usé _mm256_fmadd_ps y ahora la versión AVX2 + FMA es más rápida.No estoy seguro de por qué el compilador no hará esto por mí. Ahora estoy recibiendo alrededor de 80 GFLOPS (110% de los fracasos máximos sin FMA) para más de 1000x1000 matrices. En caso de que alguien no confíe en mi cálculo del fracaso máximo aquí es lo que hice.

peak flops (no FMA) = frequency * simd_width * ILP * cores
                    = 2.3GHZ    * 8          * 2   * 2     =  73.2 GFLOPS
peak flops (with FMA) = 2 * peak flops (no FMA)            = 146.2 GFLOPS

Mi CPU en modo turbo cuando uso ambos núcleos es de 2.3 GHz. Obtengo 2 para ILP porque Ivy Bridge puede hacer una multiplicación de AVX y una adición de AVX al mismo tiempo (y he desenrollado el bucle varias veces para asegurar esto).

Solo estoy obteniendo alrededor del 55% de los fracasos máximos (con FMA). No estoy seguro de por qué, pero al menos estoy viendo algo ahora.

Un efecto secundario es que ahora obtengo un pequeño error cuando me comparo con un algoritmo de multiplicación de matrices simple en el que sé que confío. Creo que eso se debe al hecho de que FMA solo tiene un modo de redondeo en lugar de lo que normalmente sería dos (lo que irónicamente rompe las reglas de punto flotante de IEEE, aunque probablemente sea mejor).

Editar:

Alguien necesita rehacer¿Cómo logro el máximo teórico de 4 FLOPs por ciclo? pero haz 8 FLOPS de punto flotante doble por ciclo con Haswell.

Editar

En realidad, Mysticial ha actualizado su proyecto para apoyar a FMA3 (vea su respuesta en el enlace de arriba). Ejecuté su código en Windows8 con MSVC2012 (porque la versión de Linux no se compilaba con soporte de FMA). Aquí están los resultados.

Testing AVX Mul + Add:
Seconds = 22.7417
FP Ops  = 768000000000
FLOPs   = 3.37705e+010
sum = 17.8122

Testing FMA3 FMA:
Seconds = 22.1389
FP Ops  = 1536000000000
FLOPs   = 6.938e+010
sum = 333.309

Eso es 69.38 GFLOPS para FMA3 para punto flotante doble. Para el punto flotante único, necesito duplicarlo para que sea 138.76 SP GFLOPS. Calculo que mi pico es 146.2 SP GFLOPS.Eso es el 95% del pico! En otras palabras, debería poder mejorar mi código GEMM un poco (aunque ya es bastante más rápido que Eigen).

Respuestas a la pregunta(2)

Su respuesta a la pregunta