FMA3 in GCC: Wie wird es aktiviert?

Ich habe einen i5-4250U mit AVX2 und FMA3. Ich teste einen dichten Matrixmultiplikationscode in GCC 4.8.1 unter Linux, den ich geschrieben habe. Nachfolgend finden Sie eine Liste mit drei verschiedenen Möglichkeiten, die ich kompiliere.

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

Die SSE2- und AVX-Version unterscheiden sich deutlich in der Leistung. Die AVX2 + FMA ist jedoch nicht besser als die AVX-Version. Ich verstehe das nicht. Ich bekomme über 80% der Peak-Flops der CPU, vorausgesetzt, es gibt keine FMA, aber ich denke, ich sollte mit FMA viel besser abschneiden können. Die Matrixmultiplikation sollte direkt von der FMA profitieren. Ich mache normalerweise acht Dot-Produkte auf einmal in AVX. Wenn ich nachschauemarch=native es gibt:

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 ...

So kann ich sehen, dass es aktiviert ist (nur um sicherzugehen, dass ich hinzugefügt habe-mfma aber es macht keinen unterschied).ffast-math sollte ein entspanntes Gleitkommamodell ermöglichenVerwendung der FMA-Anweisungen (Fused Multiply-Add) mit SSE / AVX

Bearbeiten:

Aufgrund der Kommentare von Mysticial habe ich _mm256_fmadd_ps verwendet und jetzt ist die AVX2 + FMA-Version schneller.Ich bin nicht sicher, warum der Compiler das nicht für mich tun wird. Ich bekomme jetzt ungefähr 80 GFLOPS (110% der Peak-Flops ohne FMA) für über 1000x1000 Matrizen. Falls jemand meiner Peak-Flop-Berechnung nicht vertraut, habe ich dies getan.

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

Meine CPU im Turbo-Modus bei Verwendung beider Kerne ist 2,3 GHz. Ich bekomme 2 für ILP, weil Ivy Bridge eine AVX-Multiplikation und eine AVX-Addition gleichzeitig ausführen kann (und ich habe die Schleife mehrmals abgerollt, um dies sicherzustellen).

Ich bekomme nur ca. 55% der Peak Flops (mit FMA). Ich bin mir nicht sicher warum, aber zumindest sehe ich jetzt etwas.

Ein Nebeneffekt ist, dass ich jetzt einen kleinen Fehler erhalte, wenn ich mit einem einfachen Matrixmultiplikationsalgorithmus vergleiche, von dem ich weiß, dass ich ihm vertraue. Ich denke, das liegt an der Tatsache, dass die FMA nur einen Rundungsmodus anstelle von normalerweise zwei hat (was ironischerweise gegen IEEE-Gleitkommaregeln verstößt, obwohl es wahrscheinlich besser ist).

Bearbeiten:

Jemand muss wiederholenWie erreiche ich das theoretische Maximum von 4 FLOPs pro Zyklus? Führen Sie jedoch mit Haswell 8 doppelte Fließkomma-FLOPS pro Zyklus durch.

Bearbeiten

Tatsächlich hat Mysticial sein Projekt aktualisiert, um FMA3 zu unterstützen (siehe seine Antwort im obigen Link). Ich habe seinen Code in Windows8 mit MSVC2012 ausgeführt (da die Linux-Version nicht mit FMA-Unterstützung kompiliert wurde). Hier sind die Ergebnisse.

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

Das sind 69,38 GFLOPS für FMA3 für Double Floating Point. Für ein einzelnes Gleitkomma muss ich es verdoppeln, damit das 138,76 SP GFLOPS sind. Ich berechne meinen Peak auf 146,2 SP GFLOPS.Das sind 95% der Spitze! Mit anderen Worten, ich sollte in der Lage sein, meinen GEMM-Code ein bisschen zu verbessern (obwohl er bereits ein bisschen schneller ist als Eigen).

Antworten auf die Frage(2)

Ihre Antwort auf die Frage