Как воспользоваться преимуществами AVX2 на новых процессорах, одновременно поддерживая старые процессоры? - PullRequest
2 голосов
/ 08 апреля 2019

У меня есть алгоритм обработки изображений, который я реализовал в трех версиях:

  1. Использование набора команд x64 (rax, rbx, ... registers)
  2. Использование набора инструкций SSE(регистры xmm)
  3. Использование набора инструкций AVX2 (регистры ymm)

Производительность улучшается с каждым шагом оптимизации.Однако мне нужно запустить его на старых процессорах, которые поддерживают только SSE (я использую платформу x64 на Visual Studio, поэтому все мои процессоры поддерживают SSE).

В Visual Studio есть параметр, который называется «Включить расширенное».Instruction Set ", который я должен установить на /arch:AVX2, чтобы получить лучшую производительность на моих новых процессорах.Однако с этим параметром исполняемый файл вылетает на моих старых процессорах.Если я установлю «Включить расширенный набор инструкций» на /arch:SSE2, то мой исполняемый файл будет работать на старых процессорах, но я не получу максимальную производительность на новых процессорах.

Я измерил скорость выполнения для всех комбинаций флагов компилятораи наборы инструкций, используя мой новый процессор.Сводка приведена в следующей таблице.

Instruction set ||        Compilation flags
which I use     ||     /arch:SSE     /arch:AVX2
----------------++------------------------------------
x64             ||     bad (4.6)      bad (4.5)
SSE             ||     OK  (1.9)      bad (5.3)
AVX2            ||     bad (3.2)     good (1.4)

Мой векторизованный код использует встроенные функции, например:

// AVX2 - conversion from 32-bit to 16-bit
temp = _mm256_packus_epi32(input[0], input[1]);
output = _mm256_permute4x64_epi64(temp, 0xd8);
// SSE - choosing one of two results using a mask
result = _mm_blendv_epi8(result0, result1, mask);

Я предполагаю, что если Visual Studio получит компиляцию /arch:AVX2флаг, он выполняет все необходимые оптимизации для AVX2, например, испуская vzeroupper.Так что я не вижу, как можно добиться максимальной производительности на обоих типах процессоров с одним и тем же скомпилированным исполняемым файлом.

Возможно ли это?Если да, какие флаги компиляции мне нужно передать компилятору Visual Studio?

1 Ответ

2 голосов
/ 08 апреля 2019

Способ, которым Intel делает это, - диспетчеризация процессора (проверьте флаг ax в документации компилятора Intel). Флаг ax специфичен для компилятора Intel и обеспечивает неявную диспетчеризацию процессора. Он не доступен на VS, поэтому вы должны сделать это вручную.

В начале своего кода вы проверяете характеристики своего процессора и устанавливаете где-то глобальные флаги.

Затем, когда вы вызываете одну из своих функций, вы сначала проверяете состояние флага, чтобы увидеть, какую функцию вы на самом деле хотите вызвать.

Таким образом, вы получаете разные варианты своих функций. Чтобы справиться с этим, вы можете поместить их в другое определенное пространство имен (как это делает libsimdpp) или вручную изменить имя функции (как это делает компилятор Intel).

Кроме того, любой 64-битный процессор имеет встроенную поддержку SSE2, поэтому случай 1 отсутствует.

...