Отключить функции AVX2 на процессорах, отличных от Haswell

Я написал код AVX2 для запуска на процессоре Haswell i7. Та же самая кодовая база также используется на процессорах не Haswell, где тот же код должен быть заменен их эквивалентами SSE. Мне было интересно, есть ли способ для компилятора игнорировать инструкции AVX2 на процессорах, отличных от Haswell. Мне нужно что-то вроде:

public void useSSEorAVX(...){
IF (compiler directive detected AVX2)
AVX2 code (this part is ready)
ELSE
SSE code  (this part is also ready)
}
}

Прямо сейчас я комментирую связанный код перед компиляцией, но должен быть более эффективный способ сделать это. Я использую Ubuntu и GCC. Спасибо за вашу помощь.

2

Решение

Если вы просто хотите сделать это в время компиляции тогда вы можете сделать это:

#ifdef __AVX2__
// AVX2 code
#elif __SSE__
// SSE code
#else
// scalar code
#endif

Обратите внимание, что когда вы компилируете с gcc -mavx2 ... затем __AVX2__ определяется автоматически. Аналогично для __SSE__, (Обратите также внимание, что вы можете проверить, что предопределено вашим компилятором для любого данного переключения командной строки, используя заклинание gcc -dM -E -mavx2 - < /dev/null.)

Если вы хотите выполнить диспетчеризацию во время выполнения, тогда это немного сложнее.

5

Другие решения

Я не думаю, что это хорошая идея сделать отдельный исполняемый файл, если вам не нужно. В вашем случае вы можете сделать диспетчер процессора. Я сделал это недавно для GCC и Visual studio.

Давайте предположим, что у вас есть функция с именем product для SSE и AVX. Вы помещаете версию SSE в файл product_SSE.cpp, а версию AVX2 — в файл product_AVX2.cpp. Вы компилируете каждый отдельно (например, с -msse2 а также -mavx2). Затем сделайте такой модуль:

extern "C" void product_SSE(float *a, float *b, float *c, int n);
extern "C" void product_AVX2(float *a, float *b, float *c, int n);
void product_dispatch(float *a, float *b, float *c, int n);
void (*fp)(float* a, float *b, float *c, int n) = product_dispatch;

inline void product_dispatch(float *a, float *b, float *c, int n) {
int iset = instrset_detect();
if(iset==8) {
fp = product_AVX2
}
else {
fp = product_SSE
}
fp(a,b,c,n);
}

inline void product(float *a, float *b, float*c, int bs) {
fp(a,b,c,n);
}

Вы компилируете этот модуль с нижним общим набором команд (например, с SSE2). Теперь, когда вы звоните продукт, он сначала звонит product_dispatch устанавливает указатель на функцию fpлибо product_AVX2 или же product_SSE а затем вызывает функцию из указателя функции. Второй раз звонишь productон прыгает прямо на product_AVX2или же product_SSE, Таким образом, вам не нужно иметь отдельный исполняемый файл.

11

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector