为什么我的矢量化平滑功能会变慢?

时间:2013-06-29 20:14:11

标签: c++ vectorization sse smoothing

我编写了两个版本的平滑函数,它将内核应用于9坐标的输出。

float PerlinHeightMapGenerator::defaultSmooth(int x, int z, const float kernel[9])
{
    const float top = defaultNoise(x - 1, z + 1) * kernel[0] + defaultNoise(x, z + 1) * kernel[1] + defaultNoise(x + 1, z + 1) * kernel[2];
    const float middle = defaultNoise(x - 1, z) * kernel[3] + defaultNoise(x, z) * kernel[4] + defaultNoise(x + 1, z) * kernel[5];
    const float bottom = defaultNoise(x - 1, z - 1) * kernel[6] + defaultNoise(x, z - 1) * kernel[7] + defaultNoise(x + 1, z - 1) * kernel[8];

    const float total = (top + middle + bottom);

    return total;
}

float PerlinHeightMapGenerator::defaultSmooth(int x, int z, const XMVECTOR kernel[3])
{
    const XMVECTOR top = XMVector3Dot(XMVectorSet(defaultNoise(x - 1, z + 1), defaultNoise(x, z + 1), defaultNoise(x + 1, z+ 1), 0), kernel[0]);
    const XMVECTOR middle = XMVector3Dot(XMVectorSet(defaultNoise(x - 1, z), defaultNoise(x, z), defaultNoise(x + 1, z), 0), kernel[1]);
    const XMVECTOR bottom = XMVector3Dot(XMVectorSet(defaultNoise(x - 1, z - 1), defaultNoise(x, z - 1), defaultNoise(x + 1, z - 1), 0), kernel[2]);

    XMFLOAT4 answer;
    XMStoreFloat4(&answer, XMVectorAdd(top, XMVectorAdd(middle, bottom)));
    return answer.x;

}

第二个版本使用向量指令,但是对于我正在使用的输入要慢得多(为整个程序的总执行时间增加了近200毫秒)。矢量化版本不应该更快,因为它可以一次调用三个“defaultNoise”,并且还可以同时进行乘法运算吗?

如果相关,“defaultNoise(x,z)”执行此操作:

float PerlinHeightMapGenerator::defaultNoise(int x, int z)
{
    int n = x + z * 57;
    n = (n<<13) ^ n;
    return static_cast<float>( 1.0f - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0f); 
};
编辑:我已经尝试了一些我不理解的结果的测试。 首先,我尝试更改它,因此向量化函数采用9个浮点数组,然后将它们复制到函数中的向量;什么都不做。

然后我尝试更改代码,看看如果实际上没有使用任何内核向量会发生什么。首先,将所有内核实例替换为XMVectorSet(1,2,3,4),以便代码为:

const XMVECTOR top = XMVector3Dot(XMVectorSet(defaultNoise(x - 1, z + 1), defaultNoise(x, z + 1), defaultNoise(x + 1, z+ 1), 0), XMVectorSet(1, 2, 3, 4));
    const XMVECTOR middle = XMVector3Dot(XMVectorSet(defaultNoise(x - 1, z), defaultNoise(x, z), defaultNoise(x + 1, z), 0), XMVectorSet(1, 2, 3, 4));
    const XMVECTOR bottom = XMVector3Dot(XMVectorSet(defaultNoise(x - 1, z - 1), defaultNoise(x, z - 1), defaultNoise(x + 1, z - 1), 0), XMVectorSet(1, 2, 3, 4));

这将程序的执行时间从4秒减少到不到2秒(减少50%)。

然后我尝试用内核[0]替换第一个XMVectorSet(1,2,3,4),这将执行时间增加到大约2100毫秒。用内核[1]替换第二个XMVectorSet(1,2,3,4)将时间增加到2700毫秒;替换最后的第三个向量使时间回到4秒。

我还尝试将浮点数复制到函数内部的向量而不是在调用它之前,结果是相同的。

编辑2:看起来XMVectorSet(1,2,3,4)是一种特殊情况。也许它更快,因为它是4个整数;用XMVectorSet(.0357143f,0.0714286f,0.0357143f,0)替换它会使其速度降低到原始速度。

我仍然不明白为什么矢量化版本会慢一些。

0 个答案:

没有答案