我正在尝试在我的编译器 (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 在 4.8.2 版为我的代码生成 AVX2;不确定早期版本)。
如果我必须对 int32_t
进行计算,我可以考虑将它们转换为 float
并返回。但是,由于我使用 int16_t
,它没有帮助。
关于c++ - 为什么 MSVC 的自动矢量化不使用 AVX2?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26864623/