Почему моя векторизованная функция сглаживания медленнее?

Я написал две версии функции сглаживания, которая применяет ядро ​​к выводу 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%).

Затем я попытался заменить первый XMVectorSet (1, 2, 3, 4) обратно ядром [0], и это увеличило время выполнения примерно до 2100 миллисекунд. Замена второго XMVectorSet (1, 2, 3, 4) на ядро ​​[1] увеличила время до 2700 миллисекунд; заменив окончательный, третий вектор вернул время до 4 секунд.

Я попытался также скопировать числа с плавающей точкой в ​​векторы внутри функции вместо того, чтобы вызывать ее, и результат тот же.

РЕДАКТИРОВАТЬ 2: Похоже, XMVectorSet (1, 2, 3, 4) является особым случаем. Может быть, это быстрее, потому что это 4 дюйма; замена его на XMVectorSet (.0357143f, 0,0714286f, 0,0357143f, 0) замедляет его до первоначальной скорости.

Я до сих пор не понимаю, почему векторизованная версия медленнее.

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]