2015-03-09 10 views
31

Próbuję zoptymalizować niektóre obliczenia macierzy i zastanawiałem się, czy można było wykryć podczas kompilacji, czy SSE/SSE2/AVX/AVX2/AVX-512/AVX-128-FMA/KCVI [1] jest włączony przez kompilator? Idealnie dla GCC i Clang, ale mogę poradzić sobie tylko z jednym z nich.Jak wykryć dostępność SSE/SSE2/AVX/AVX2/AVX-512/AVX-128-FMA/KCVI podczas kompilacji?

Nie jestem pewien, czy to możliwe i być może użyję własnego makra, ale wolałbym go raczej wykryć i poprosić o jego wybór.


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

+1

Co dokładnie chcesz przetestować? Czy chcesz przetestować, czy kompilator będzie produkował instrukcje AVX? Ważne jest, aby pamiętać, że tylko dlatego, że kompilator jest gotowy do ich wytworzenia, nie oznacza, że ​​procesor, który ostatecznie uruchomi Twój program, również go obsłuży (nawet jeśli zarówno kompilacja, jak i wykonanie nastąpi na tym samym komputerze). – ArjunShankar

+1

@ArjunShankar Chcę wiedzieć, czy na przykład włączono avx podczas kompilacji z -mavx. –

+2

Należy również zauważyć, że obsługa CPU i obsługa systemu operacyjnego to dwie różne rzeczy. Procesor może obsługiwać SSE, ale system operacyjny może nie obsługiwać SSE (która wymaga systemu operacyjnego do zapisywania rejestrów XMM podczas przełączania kontekstowego). Zobacz, na przykład, [Sprawdzanie dla SSE] (http://wiki.osdev.org/SSE#Checking_for_SSE) na wiki OSDev. – jww

Odpowiedz

51

Większość kompilatorów automatycznie określić:

__SSE__ 
__SSE2__ 
__SSE3__ 
__AVX__ 
__AVX2__ 

itp, według cokolwiek Przełączniki wiersza polecenia jesteś przejazdem. Można łatwo sprawdzić z gcc (lub gcc kompatybilne kompilatory takie jak brzękiem), na przykład:

$ 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ć predefiniowanych makr dla domyślnej kompilacji na konkretnej 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 Bezpośrednie

$ 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 ujawnione dodatkowe AVX-512 (patrz ISA extensions podzbiory). GCC (wersja 7) obsługuje flagi kompilatora i symbole preprocesora związane z podzbiorów 4FMAPS, 4VNNIW, IFMA, VBMI i VPOPCNTDQ z 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

To jest po prostu idealne! –

+0

Należy pamiętać, że makra SSE nie będą działać z Visual C++. Zamiast tego musisz użyć _M_IX86_FP: https://msdn.microsoft.com/en-us/library/b0084kay.aspx –

+1

@ Remi: tak, typowo obawiam się - najłatwiej jest po prostu zdefiniować makra SSE w swoim projekt lub plik makefile, jeśli jesteś zmuszony do obsługi MSVC. –

Powiązane problemy