SIMD и разница между упакованной и скалярной двойной точностью
Я читаю руководство по интуиции Intel во время реализации поддержки SIMD. У меня несколько путаниц, и мои вопросы таковы, как показано ниже.
-
__m128 _mm_cmpeq_ps (__m128 a, __m128 b)
Документация говорит, что она используется для сравнения упакованных точек с плавающей запятой. Что означает "упакованный"? Нужно ли мне как-то накапливать свои значения float, прежде чем я смогу их использовать?
-
Для двойной точности существуют такие функции, как _mm_cmpeq_sd
, что означает сравнение "более низких" элементов с плавающей запятой двойной точности. Что означают нижние и верхние элементы двойной точности? Могу ли я использовать их для сравнения элементов типа С++ double
или нет? Или мне нужно обработать их каким-то образом, прежде чем сравнивать их?
Ответы
Ответ 1
В SSE регистры 128 бит могут быть представлены как 4 элемента из 32 бит.
SSE определяет два типа операций; скалярный и упакованный. Скалярная операция работает только с наименее значимым элементом данных (бит 0 ~ 31), а упакованная операция вычисляет все четыре элемента параллельно.
_mm_cmpeq_sd
будет сравнивать только наименее значимый элемент данных (первые 32 бита) двух операндов, тогда как _mm_cmpeq_ps
будет сравнивать каждую группу из 32 бит параллельно.
Если вы используете 64 бита в два раза, вы можете упаковать двойную пару, чтобы использовать 128-битное пространство. Таким образом, _mm_cmpeq_ps
мог бы сделать два компаранинга из 4 двойных параллельно.
Если вы хотите сделать только одно сравнение за раз, , вы можете использовать _mm_cmpeq_pd
для сравнения двух 64-битных двойных.
Обратите внимание, что _mm_cmpeq_pd
является SSE2, а _mm_cmpeq_ps
является SSE.
Ответ 2
В этом контексте "упакованный" означает "несколько одинаковых типов, помещенных в один кусок" - поэтому "упакованная точка с плавающей точкой с одной точностью" означает 4 * 32-битные числа с плавающей запятой, сохраненные в виде 128-битного значения.
Вам либо нужно "упаковать" каждое значение в регистр, используя различные инструкции PACK*
, либо данные уже "упакованы" в память, например. массив (кратных) 4 значений с плавающей запятой [которые соответствующим образом выровнены].
Скаляр означает "одно значение" в нижних битах n
регистра (например, a double
будет низким 64 бит 128-битного регистра SSE).