Jak wykryć dostępność SSE/SSE2/AVX/AVX2/AVX-512/AVX-128-FMA/KCVI w czasie kompilacji?

Próbuję zoptymalizować niektóre obliczenia macierzy i zastanawiałem się, czy jest możliwe wykrycie w czasie kompilacji, jeśli SSE / SSE2 / AVX/AVX2 / AVX-512/AVX-128-FMA / KCVI[1] jest włączona przez kompilator ? Idealnie dla GCC i Clang, ale poradzę sobie tylko z jednym z nich.

Nie jestem pewien, czy jest to możliwe i być może użyję własnego makra, ale wolałbym je wykryć i poprosić Użytkownika o wybranie go.


[1] "KCVI" oznacza Knights Corner Vector Optymalizacja instrukcji. Biblioteki takie jak FFTW wykrywają/wykorzystują te nowsze optymalizacje instrukcji.

Author: Trevor Boyd Smith, 2015-03-09

1 answers

Większość kompilatorów automatycznie zdefiniuje:

__SSE__
__SSE2__
__SSE3__
__AVX__
__AVX2__

Itd., zgodnie z przełącznikami linii poleceń, które przechodzisz. Możesz to łatwo sprawdzić za pomocą GCC (lub kompilatorów zgodnych z gcc, takich jak clang), jak:

$ 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

Lub:

$ 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

Lub po prostu sprawdzić wstępnie zdefiniowane makra dla domyślnej kompilacji na danej platformie:

$ 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
Nowsze procesory Intela obsługują AVX-512, który nie jest monolitycznym zestawem instrukcji. Można zobaczyć wsparcie dostępne z GCC (Wersja 6.2) Dla dwóch przykładów poniżej.

Oto Rycerze lądują:

$ 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

Oto 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 ujawnił dodatkowe podzbiory AVX-512 (zobacz rozszerzenia ISA ). GCC (wersja 7) obsługuje flagi kompilatora i symbole preprocesora związane z podzbiorami 4FMAPS, 4VNNIW, IFMA, VBMI i VPOPCNTDQ 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
 68
Author: Paul R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-18 00:23:28