Я пытаюсь использовать векторизацию в моем компиляторе (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?
Visual Studio легко создает код AVX2 при выполнении арифметики с плавающей запятой. Я думаю, этого достаточно, чтобы объявить, что «VS2013 поддерживает AVX2».
Однако, что бы я ни делал, VS2013 не создавал код AVX2 для целочисленных вычислений (ни int16_t
ни int32_t
сработало), поэтому я думаю, что это вообще не поддерживается (gcc создает AVX2 для моего кода в версии 4.8.2; не уверен насчет более ранних версий).
Если бы я должен был сделать расчеты на int32_t
Я мог бы рассмотреть возможность преобразования их в float
и назад. Тем не менее, так как я использую int16_t
это не помогает