INTEL SIMD: почему умножение на месте происходит так медленно?

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

Самое простое можно свести к следующему:

void scale(float* dst, const float* src, int count, float factor)
{
__m128 factorV = _mm_set1_ps(factorV);

for(int i = 0; i < count; i+= 4)
{
__m128 in = _mm_load_ps(src);
in = _mm_mul_ps(in, factorV);
_mm_store_ps(dst, in);

dst += 4;
src += 4;
}
}

код тестирования:

for(int i = 0; i < 1000000; i++)
{
scale(alignedMemPtrDst, alignedMemPtrSrc, 256, randomFloatAbsRange1);
}

При тестировании, то есть многократном использовании этой функции на ЖЕ буферах, я обнаружил, что, если dst и src одинаковы, скорость одинакова. Если они разные, это примерно в 70 раз быстрее. Основные циклы записываются при записи (то есть _mm_store_ps)

Интересно то же самое поведение не распространяется на сложение, то есть + = хорошо работает, только * = это проблема ..

На это ответили в комментариях. Это ненормально во время искусственного тестирования.

4

Решение

Ваш factor производить субнормальный результат? Ненулевой, но меньше, чем FLT_MIN? Если за пределами этого есть цикл, который повторяет один и тот же блок на месте, числа могут стать достаточно маленькими, чтобы требовать медленных передач FP.

(Оказывается, да это была проблема для ОП).

Повторное умножение на месте делает числа все меньше и меньше с коэффициентом ниже 1,0. Копирование и масштабирование в другой буфер каждый раз использует одни и те же входные данные.

Это не займет дополнительное время, чтобы произвести +-Inf или же NaN результат, но это делает для постепенного снижения нагрузки до субнормального по крайней мере на процессорах Intel. Это одна из причин -ffast-math устанавливает DAZ / FTZ — сбрасывать в ноль при недостаточном расходе.


Я думаю, что я читал, что AMD не поддерживает микрокодирование FP-ассистента обработки субнормалей, но у Intel есть.

На процессорах Intel есть счетчик производительности для fp_assist.any которая рассчитывает, когда для результата, превышающего нормальный, требуются дополнительные микрокоды для обработки специального случая. (Я думаю, что это так же навязчиво, как и для внешнего интерфейса и исполнительного директора. Однако, это определенно медленно.)


Почему денормализованные операции с точки зрения аппаратной архитектуры намного медленнее, чем у других операций?

Почему icc генерирует странную сборку для простого main? (показывает, как ICC устанавливает FTZ / DAZ в начале main, с настройкой быстрой математики по умолчанию.)

6

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

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

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