如何让VC编译器更好地用SIMD优化我的代码?

时间:2017-01-14 07:52:00

标签: visual-c++ optimization sse simd

我现在正在学习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;
}

1 个答案:

答案 0 :(得分:1)

Visual C ++ 2013或更高版本将默认为x86使用/arch:SSE2,但您仍应检查Visual Studio项目中的设置,以确保它未明确设置为其他内容。对于x64,/arch:SSE2是隐含的。

Visual C ++唯一自动生成多通道(如ADDPS)而不是单通道(ADDSS)指令的时间是由自动向量化器引起的。有关详细信息,请参阅MSDN并特别注意/Qvec-report:2开关 - 请注意,在调试配置中常见的禁用优化时不会发生这种情况。

使用显式内在函数可以更好地完成大多数SIMD(多通道)代码生成。有关这种编码风格的大量示例,请参阅DirectXMath