2015-03-09 5 views
31

Ich versuche, einige Matrixberechnungen zu optimieren, und ich frage mich, ob es möglich war, zur Kompilierzeit festzustellen, ob SSE/SSE2/AVX/AVX2/AVX-512/AVX-128-FMA/KCVI [1] wird vom Compiler aktiviert? Ideal für GCC und Clang, aber ich kann nur mit einem von ihnen fertig werden.Wie kann SSE/SSE2/AVX/AVX2/AVX-512/AVX-128-FMA/KCVI Verfügbarkeit zur Kompilierzeit erkannt werden?

Ich bin mir nicht sicher, ob es möglich ist, und vielleicht werde ich mein eigenes Makro verwenden, aber ich würde lieber es eher erkennen und den Benutzer bitten, es auszuwählen.


[1] "KCVI" steht für Ritter Corner Vektorinstruktions Optimierungen. Bibliotheken wie FFTW erkennen/nutzen diese neueren Befehlsoptimierungen.

+1

Was genau wollen Sie testen? Möchten Sie testen, ob der Compiler AVX-Anweisungen erstellt? Es ist wichtig, daran zu denken, dass, nur weil der Compiler bereit ist, sie zu produzieren, nicht bedeutet, dass die CPU, die Ihr Programm letztendlich ausführen wird, es auch unterstützen wird (selbst wenn Kompilierung und Ausführung auf demselben Rechner stattfinden). – ArjunShankar

+1

@ArjunShankar Ich möchte wissen, ob zum Beispiel avx während der Kompilierung mit -mavx aktiviert wurde. –

+2

Beachten Sie außerdem, dass CPU-Unterstützung und Betriebssystemunterstützung zwei verschiedene Dinge sind. Die CPU unterstützt möglicherweise SSE, aber das Betriebssystem unterstützt möglicherweise SSE nicht (was erfordert, dass das OS XMM-Register während einer Kontextumschaltung speichert). Sehen Sie zum Beispiel [Nach SSE suchen] (http://wiki.osdev.org/SSE#Checking_for_SSE) im OSDev-Wiki. – jww

Antwort

51

Die meisten Compiler automatisch definieren:

__SSE__ 
__SSE2__ 
__SSE3__ 
__AVX__ 
__AVX2__ 

etc, nach was auch immer Befehlszeilenoptionen Sie sind vorbei. Sie können dies leicht mit gcc überprüfen (oder gcc-kompatible Compiler wie Klappern), wie folgt aus:

$ gcc -msse3 -dM -E - < /dev/null | egrep "SSE|AVX" | sort 
#define __SSE__ 1 
#define __SSE2__ 1 
#define __SSE2_MATH__ 1 
#define __SSE3__ 1 
#define __SSE_MATH__ 1 

oder:

$ gcc -mavx2 -dM -E - < /dev/null | egrep "SSE|AVX" | sort 
#define __AVX__ 1 
#define __AVX2__ 1 
#define __SSE__ 1 
#define __SSE2__ 1 
#define __SSE2_MATH__ 1 
#define __SSE3__ 1 
#define __SSE4_1__ 1 
#define __SSE4_2__ 1 
#define __SSE_MATH__ 1 
#define __SSSE3__ 1 

oder zu prüfen, nur die vordefinierten Makros für eine Standard-Build auf Ihrer speziellen Plattform:

$ gcc -dM -E - < /dev/null | egrep "SSE|AVX" | sort 
#define __SSE2_MATH__ 1 
#define __SSE2__ 1 
#define __SSE3__ 1 
#define __SSE_MATH__ 1 
#define __SSE__ 1 
#define __SSSE3__ 1 

Neuere Intel-Prozessoren unterstützen AVX-512, das kein monolithischer Befehlssatz ist. Man kann die Unterstützung von GCC (Version 6.2) für zwei Beispiele unten sehen.

Hier ist Ritter Landing:

$ gcc -march=knl -dM -E - < /dev/null | egrep "SSE|AVX" | sort 
#define __AVX__ 1 
#define __AVX2__ 1 
#define __AVX512CD__ 1 
#define __AVX512ER__ 1 
#define __AVX512F__ 1 
#define __AVX512PF__ 1 
#define __SSE__ 1 
#define __SSE2__ 1 
#define __SSE2_MATH__ 1 
#define __SSE3__ 1 
#define __SSE4_1__ 1 
#define __SSE4_2__ 1 
#define __SSE_MATH__ 1 
#define __SSSE3__ 1 

Hier ist Skylake AVX-512:

$ gcc -march=skylake-avx512 -dM -E - < /dev/null | egrep "SSE|AVX" | sort 
#define __AVX__ 1 
#define __AVX2__ 1 
#define __AVX512BW__ 1 
#define __AVX512CD__ 1 
#define __AVX512DQ__ 1 
#define __AVX512F__ 1 
#define __AVX512VL__ 1 
#define __SSE__ 1 
#define __SSE2__ 1 
#define __SSE2_MATH__ 1 
#define __SSE3__ 1 
#define __SSE4_1__ 1 
#define __SSE4_2__ 1 
#define __SSE_MATH__ 1 
#define __SSSE3__ 1 

Intel zusätzliche AVX-512 Untergruppen (siehe ISA extensions) offenbart hat. GCC (Version 7) unterstützt Compiler-Flags und Präprozessorsymbole im Zusammenhang mit den 4FMAPS, 4VNNIW, IFMA, VBMI und VPOPCNTDQ Teilmengen von AVX-512:

for i in 4fmaps 4vnniw ifma vbmi vpopcntdq ; do echo "==== $i ====" ; gcc -mavx512$i -dM -E - < /dev/null | egrep "AVX512" | sort ; done 
==== 4fmaps ==== 
#define __AVX5124FMAPS__ 1 
#define __AVX512F__ 1 
==== 4vnniw ==== 
#define __AVX5124VNNIW__ 1 
#define __AVX512F__ 1 
==== ifma ==== 
#define __AVX512F__ 1 
#define __AVX512IFMA__ 1 
==== vbmi ==== 
#define __AVX512BW__ 1 
#define __AVX512F__ 1 
#define __AVX512VBMI__ 1 
==== vpopcntdq ==== 
#define __AVX512F__ 1 
#define __AVX512VPOPCNTDQ__ 1 
+2

Das ist einfach perfekt! –

+0

Beachten Sie, dass die SSE-Makros nicht mit Visual C++ funktionieren. Sie müssen stattdessen _M_IX86_FP verwenden: https://msdn.microsoft.com/en-us/library/b0084kay.aspx –

+1

@ Rémi: Ja, typisch ich fürchte - die einfachste Sache ist, nur die SSE-Makros in Ihrem zu definieren Projekt oder Makefile, wenn Sie MSVC unterstützen müssen. –

Verwandte Themen