我正在尝试在我的编译器(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 方式对其进行矢量化呢?