2015-03-09 7 views
31

Я пытаюсь оптимизировать некоторые вычисления матрицы, и мне было интересно узнать, удалось ли обнаружить во время компиляции, если SSE/SSE2/AVX/AVX2/AVX-512/AVX-128-FMA/KCVI [1] включен компилятором? Идеально для GCC и Clang, но я могу справиться только с одним из них.Как определить доступность SSE/SSE2/AVX/AVX2/AVX-512/AVX-128-FMA/KCVI во время компиляции?

Я не уверен, что это возможно, и, возможно, я буду использовать свой собственный макрос, но я предпочел бы его обнаружить и попросить пользователя его выбрать.


[1] "KCVI" означает Knights Corner Vector Инструкция оптимизаций. Библиотеки, такие как FFTW, обнаруживают/используют эти новые оптимизации инструкций.

+1

Что именно вы хотите проверить? Вы хотите проверить, что компилятор будет создавать инструкции AVX? Важно помнить, что только потому, что компилятор готов к их выпуску, это не означает, что процессор, который будет запущен в вашей программе, также будет поддерживать его (даже если компиляция и исполнение происходят на одной машине). – ArjunShankar

+1

@ArjunShankar Я хочу знать, был ли avx включен во время компиляции с -mavx. –

+2

Также обратите внимание, что поддержка ЦП и поддержка ОС - это две разные вещи. ЦП может поддерживать SSE, но ОС может не поддерживать SSE (для чего требуется, чтобы ОС сохраняла регистры XMM во время контекстного переключателя). См., Например, [Проверка для SSE] (http://wiki.osdev.org/SSE#Checking_for_SSE) в вики OSDev. – jww

ответ

51

Большинство компиляторов автоматически определяют:

__SSE__ 
__SSE2__ 
__SSE3__ 
__AVX__ 
__AVX2__ 

и т.д., в соответствии с любой командной строки вы передаете. Вы можете легко проверить это с помощью GCC (или GCC-совместимые компиляторы, такие как лязг), как это:

$ 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 

или:

$ 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 

или просто проверить заранее определенные макросы для сборки по умолчанию на вашей конкретной платформе:

$ 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 

Новые процессоры Intel поддерживают AVX-512, который не является монолитным набором команд. Можно увидеть поддержку, доступную от GCC (версия 6.2), для двух примеров ниже.

Здесь рыцари Посадка:

$ 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 

Здесь 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 раскрыл дополнительные AVX-512 подмножеств (см ISA extensions). GCC (версия 7) поддерживает флаги компилятора и препроцессор символы, связанные с подмножествами 4FMAPS, 4VNNIW, IFMA, VBMI и 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 
+2

Это просто отлично! –

+0

Обратите внимание, что макросы SSE не будут работать с Visual C++. Вместо этого вы должны использовать _M_IX86_FP: https://msdn.microsoft.com/en-us/library/b0084kay.aspx –

+1

@ Rémi: да, типично я боюсь - проще всего просто определить макросы SSE в вашем проекта или файла makefile, если вы вынуждены поддерживать MSVC. –