我正在尝试在编译器(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/