【发布时间】: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
-
你试过单循环吗?
标签: visual-c++ optimization sse simd