Почему автоматическая векторизация MSVC не использует AVX2?

Я пытаюсь использовать векторизацию в моем компиляторе (Microsoft Visual Studio 2013). Одна из проблем, с которыми я сталкиваюсь, заключается в том, что она не хочет использовать AVX2. Исследуя эту проблему, я построил следующий пример, который вычисляет сумму из 16 чисел, каждое из которых 16-разрядное.

int16_t input1[16] = {0};
int16_t input2[16] = {0};
... // fill the arrays with some data

// Calculate the sum using a loop
int16_t output1[16] = {0};
for (int x = 0; x < 16; x++){
output1[x] = input1[x] + input2[x];
}

Компилятор векторизует этот код, но только в соответствии с инструкциями SSE:

vmovdqu  xmm1, xmmword ptr [rbp+rax]
lea      rax, [rax+10h]
vpaddw   xmm1, xmm1, xmmword ptr [rbp+rax+10h]
vmovdqu  xmmword ptr [rbp+rax+30h], xmm1
dec      rcx
jne      main+0b0h

Чтобы убедиться, что компилятор имеет возможность генерировать код AVX2, я написал те же вычисления следующим образом:

// Calculate the sum using one AVX2 instruction
int16_t output2[16] = {0};
__m256i in1 = _mm256_loadu_si256((__m256i*)input1);
__m256i in2 = _mm256_loadu_si256((__m256i*)input2);
__m256i out2 = _mm256_add_epi16(in1, in2);
_mm256_storeu_si256((__m256i*)output2, out2);

Я вижу, что две части кода эквивалентны (то есть output11 равно output2 после того, как они выполнены).

И он выводит инструкции AVX2 для второй части кода:

vmovdqu  ymm1, ymmword ptr [input2]
vpaddw   ymm1, ymm1, ymmword ptr [rbp]
vmovdqu  ymmword ptr [output2], ymm1

Однако я не хочу переписывать свой код для использования встроенных функций: его запись в виде цикла гораздо более естественна, совместима со старыми (только для SSE) процессорами и имеет другие преимущества.

Итак, как мне настроить мой пример, чтобы компилятор мог векторизовать его AVX2?

7

Решение

Visual Studio легко создает код AVX2 при выполнении арифметики с плавающей запятой. Я думаю, этого достаточно, чтобы объявить, что «VS2013 поддерживает AVX2».

Однако, что бы я ни делал, VS2013 не создавал код AVX2 для целочисленных вычислений (ни int16_t ни int32_t сработало), поэтому я думаю, что это вообще не поддерживается (gcc создает AVX2 для моего кода в версии 4.8.2; не уверен насчет более ранних версий).

Если бы я должен был сделать расчеты на int32_tЯ мог бы рассмотреть возможность преобразования их в float и назад. Тем не менее, так как я использую int16_tэто не помогает

0

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