如何让 VC 编译器使用 SIMD 更好地优化我的代码?
Posted
技术标签:
【中文标题】如何让 VC 编译器使用 SIMD 更好地优化我的代码?【英文标题】:How to make VC compiler optimize my code with SIMD better? 【发布时间】:2017-01-14 07:51:59 【问题描述】:我现在正在学习 SIMD,并考虑如何让编译器更好地优化我的代码。现在我正在使用 Visual C++ 2013 x86。
我有一个数组,我有另一个数组,我想这样计算:
void computeSum(float* __restrict arr, float* __restrict inp1, float* __restrict inp2, int count)
__declspec(align(16)) float* p1 = inp1;
__declspec(align(16)) float* p2 = inp2;
__declspec(align(16)) float* ret = arr;
while (count > 0)
ret[0] = p1[0] + p2[0];
ret[1] = p1[1] + p2[1];
ret[2] = p1[2] + p2[2];
ret[3] = p1[3] + p2[3];
p1 += 4;
p2 += 4;
ret += 4;
count -= 4;
我想告诉编译器数组与 16 字节边界对齐,并且任何人都没有覆盖另一个,一个循环将计算 4 个连续浮点数的总和。
但在生成的代码中,VC 更喜欢 MOVSS/ADDSS 而不是我希望的 ADDPS。
如果我将项目配置为使用 LLVM-vs2013 工具链,它会使用 ADDPS 来计算总和。
我知道如何使用编译器内部函数来编写 SIMD 代码,但这不是我想要的。
VC使用ADDPS指令还有什么提示吗?
这是完整的代码。
#include <stdio.h>
#include <stdlib.h>
void computeSum(float* __restrict arr, float* __restrict inp1, float* __restrict inp2, int count)
__declspec(align(16)) float* p1 = inp1;
__declspec(align(16)) float* p2 = inp2;
__declspec(align(16)) float* ret = arr;
while (count > 0)
ret[0] = p1[0] + p2[0];
ret[1] = p1[1] + p2[1];
ret[2] = p1[2] + p2[2];
ret[3] = p1[3] + p2[3];
p1 += 4;
p2 += 4;
ret += 4;
count -= 4;
int main()
float* inp1 = (float*)_aligned_malloc(sizeof(float) * 128, 16);
float* inp2 = (float*)_aligned_malloc(sizeof(float) * 128, 16);
float* result = (float*)_aligned_malloc(sizeof(float) * 128, 16);
for (int i = 0; i < 128; ++i)
inp1[i] = inp2[i] = i;
computeSum(result, inp1, inp2, 128);
for (int i = 0; i < 128; ++i)
printf("%f\t", result[i]);
return 0;
【问题讨论】:
您是否指定了 /arch:SSE(或类似名称)? @harold 是的,开关 /arch:SSE2 已启用。 您是否尝试过 not 展开循环? @YvesDaoust 不,我没有。谢谢你的建议。现在我尝试了( for(int i = 0; i 你试过单循环吗? 【参考方案1】:Visual C++ 2013 或更高版本将默认为 x86 使用 /arch:SSE2
,但您仍应检查 Visual Studio 项目中的设置,以确保它没有明确设置为其他内容。对于 x64,/arch:SSE2
是隐式的。
Visual C++ 唯一一次自动生成多通道(如ADDPS
)而不是单通道(ADDSS
)指令是由于自动矢量化器。有关详细信息,请参阅 MSDN 并特别注意 /Qvec-report:2
开关 - 请注意,在禁用优化时不会发生这种情况,这在调试配置中很常见。
大多数 SIMD(多通道)代码生成都可以通过显式使用来更好地完成。有关这种编码风格的大量示例,请参阅DirectXMath。
【讨论】:
了解它被称为“自动矢量化器”和启用报告的参数开关对我来说非常重要。但经过一些试验后,我仍然无法让优化器使用 addps。你能提供一段示例代码吗?谢谢以上是关于如何让 VC 编译器使用 SIMD 更好地优化我的代码?的主要内容,如果未能解决你的问题,请参考以下文章
如何编写编译器可以针对 SIMD 比较优化的代码? [复制]
如何在 Visual Studio 2015(用于 C++)中仅禁用 SIMD 自动矢量化优化?