gcc clang sse avx avx512

gcc - ¿Cómo detectar la disponibilidad de SSE/SSE2/AVX/AVX2/AVX-512/AVX-128-FMA/KCVI en tiempo de compilación?



clang avx512 (1)

Estoy tratando de optimizar algunos cálculos matriciales y me preguntaba si era posible detectar en tiempo de compilación si SSE / SSE2 / AVX / AVX2 / AVX-512 / AVX-128-FMA / KCVI [1] está habilitado por compilador? Idealmente para GCC y Clang, pero puedo manejarlo solo con uno de ellos.

No estoy seguro de que sea posible y tal vez usaré mi propia macro, pero preferiría detectarla y pedirle al usuario que la seleccione.

[1] "KCVI" significa optimizaciones de Knights Corner Vector Instruction. Las bibliotecas como FFTW detectan / utilizan estas nuevas optimizaciones de instrucciones.


La mayoría de los compiladores definirán automáticamente:

__SSE__ __SSE2__ __SSE3__ __AVX__ __AVX2__

etc., de acuerdo con cualquier cambio de línea de comando que esté pasando Puede verificar esto fácilmente con gcc (o compiladores compatibles con gcc como clang), como este:

$ 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

o:

$ 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

o simplemente verificar las macros predefinidas para una compilación predeterminada en su plataforma particular:

$ 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

Los procesadores Intel más recientes admiten AVX-512, que no es un conjunto de instrucciones monolíticas. Se puede ver el soporte disponible de GCC (versión 6.2) para dos ejemplos a continuación.

Aquí está Knights 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

Aquí está 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 ha revelado subconjuntos AVX-512 adicionales (ver extensiones ISA ). GCC (versión 7) admite indicadores de compilación y símbolos de preprocesador asociados con los subconjuntos 4FMAPS, 4VNNIW, IFMA, VBMI y VPOPCNTDQ de 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