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).