_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
,