_mm_testc_ps и _mm_testc_pd vs _mm_testc_si128

Как вы знаете, первые два являются встроенными в AVX, а второй - встроенными в SSE4.1. Оба набора встроенных функций могут использоваться для проверки на равенство 2 векторов с плавающей точкой. Мой конкретный вариант использования:

  • _mm_cmpeq_ps или же _mm_cmpeq_pd, с последующим
  • _mm_testc_ps или же _mm_testc_pd на результат, с соответствующей маской

Но AVX предоставляет эквиваленты для "старых" встроенных функций, поэтому я мог бы использовать _mm_testc_si128после приведения результата к __m128i, Мои вопросы: какой из двух вариантов использования приводит к повышению производительности, и где я могу узнать, какие устаревшие инструкции SSE предоставляет AVX.

1 ответ

Решение

К сожалению, я не внимательно прочитал вопрос. Вы говорите об использовании этих после cmpeqps, Они всегда медленнее, чем movmskps / test если у вас уже есть маска. cmpps / ptest / jcc 4 мопа. cmpps / movmskps eax, xmm0 / test eax,eax / jnz 3 мопс. (Test/ JNZ предохранитель в один моп). Кроме того, ни одна из инструкций не является многопользовательской, поэтому нет узких мест декодирования.

Использовать только ptest / vtestps/pd когда вы можете в полной мере воспользоваться операциями AND или ANDN, чтобы избежать более раннего шага. Я отправил ответы раньше, где я сравнил ptest против альтернативы. Я думаю, что нашел один случай, когда ptest была победа, но ее сложно использовать. Да, нашел это: кто-то хотел сравнить FP, что было верно для NaN == NaN. Это один из немногих случаев, когда я нашел применение для флага переноса ptest,

Если высокий элемент результата сравнения - "мусор", вы все равно можете дешево его проигнорировать с помощью movmskps:

_mm_movemask_ps(vec) & 0b0111 == 0  // tests for none of the first three being true

Это абсолютно бесплатно. Х86 test инструкция работает так же, как ptest: Вы можете использовать его с немедленной маской вместо того, чтобы проверять регистр против себя. (Это на самом деле имеет небольшую стоимость: один дополнительный байт машинного кода, потому что test eax, 3 на один байт длиннее test eax, eax, но они работают одинаково.)

См. Вики x86 для ссылок на руководства (руководство Agner Fog хорошо подходит для анализа на уровне инструкций). Существует AVX-версия каждой устаревшей инструкции SSE, но некоторые имеют ширину всего 128 бит. Все они получают дополнительный операнд (так что dest не обязательно должен быть одним из src regs), который экономит на mov инструкции по копированию регистров.


Ответ на вопрос, который вы не задавали:

ни _mm_testc_ps ни _mm_testc_si128 может быть использован для сравнения поплавков на равенство. vtestps как ptest, но работает только со знаковыми битами каждого элемента с плавающей точкой.

Они все вычисляют (~x) & y (в знаковых битах или в полном регистре), который не говорит вам, равны ли они или даже равны ли знаковые биты.

Обратите внимание, что даже проверка на битовое равенство с плавающей точкой (с pcmpeqd) не то же самое, что cmpeqps (который реализует C == оператор), потому что -0.0 не поразрядно равно 0.0, И два бит-идентичных NaN не равны друг другу. Сравнение неупорядочено (что означает, что оно не равно), если один или оба операнда NaN,

Другие вопросы по тегам