我正在尝试在编译器(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_tint32_t都不起作用),因此我想这根本不受支持(gcc在4.8.2版中为我的代码生成了AVX2;不确定关于早期版本)。

如果必须对int32_t进行计算,则可以考虑将其转换为float并返回。但是,由于我使用int16_t,所以没有帮助。

关于c++ - 为什么MSVC的自动矢量化不使用AVX2?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26864623/

10-09 01:22