我编写了两个版本的平滑函数,它将内核应用于 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%)。
然后我尝试用 kernel[0] 替换第一个 XMVectorSet(1, 2, 3, 4),这将执行时间增加到大约 2100 毫秒。将第二个 XMVectorSet(1, 2, 3, 4) 替换为 kernel[1] 将时间增加到 2700 毫秒;替换最后的第三个向量使时间恢复到 4 秒。
我还尝试将浮点数复制到函数内部的向量中,而不是在调用它之前,结果是一样的。
编辑 2: 看来 XMVectorSet(1, 2, 3, 4) 是一个特例。也许它更快,因为它是 4 个整数;用 XMVectorSet(.0357143f, 0.0714286f, 0.0357143f, 0) 替换它会减慢到原来的速度。
不过,我仍然不明白为什么矢量化版本较慢。