2016-10-01 4 views
4

Я столкнулся с fast CRC computation using PCLMULQDQ implementation. я вижу, что ребята смешать pxor и xorps инструкции сильно, как в приведенном ниже фрагменте:Использует ли использование mixor и xorps производительность?

movdqa xmm10, [rk9] 
movdqa xmm8, xmm0 
pclmulqdq xmm0, xmm10, 0x11 
pclmulqdq xmm8, xmm10, 0x0 
pxor xmm7, xmm8 
xorps xmm7, xmm0 

movdqa xmm10, [rk11] 
movdqa xmm8, xmm1 
pclmulqdq xmm1, xmm10, 0x11 
pclmulqdq xmm8, xmm10, 0x0 
pxor xmm7, xmm8 
xorps xmm7, xmm1 

Есть ли практическая причина для этого? Повышение производительности? Если да, то что лежит под этим? Или, может быть, это всего лишь стиль кодирования, для удовольствия?

+3

'xorps' является трехбайтовой инструкцией, а' pxor' занимает четыре байта. Помимо этого, [таблицы инструкций] (http://www.agner.org/optimize/instruction_tables.pdf) и [руководства по микроархитектуре] (http://www.agner.org/optimize/microarchitecture.pdf) указывают, что что это не повредит AMD, поскольку «xorps» рассматривается как целочисленный домен.Это * может * повредить производительность на pre-skylake Intel, хотя, поскольку «xorps» не может использовать столько исполнительных блоков, и могут быть задержки байпаса. – EOF

+0

@ EOF: Я предполагаю, что он настроен для Intel SnB/IvB, основанный на дате (и что он написан Intel). Выравнивание для кэша uop похоже на лучшее предположение, но, возможно, что-то происходит, избегая конфликта ресурсов, чтобы не задерживать следующий PCLMUL. –

ответ

7

TL: DR: похоже, может быть, какая-то настройка на микроархитектуру для эта конкретная последовательность кода. В этом нет ничего «общего», который поможет в других случаях.

При дальнейшем рассмотрении я думаю, что теория @Iwillnotexist Idonotexist является наиболее вероятной: это было написано не экспертом, который думал, что это может помочь. Распределение регистров большой ключ: много REX префиксы можно было бы избежать, выбрав все повторно используемые регистры в младшем 8.


XORPS работает в «плавающее» домена, на некоторых процессорах Intel (Nehalem и позже), в то время как PXOR всегда работает в домене «ivec».

Поскольку проводка каждого выхода ALU на каждый вход ALU для непосредственных результатов пересылки была бы дорогостоящей, разработчики CPU разбивают их на домены. (Пересылка сохраняет латентность записи в файл регистра и повторное чтение). Пересечение домена может занять дополнительный 1 цикл латентности (семейство Intel SnB) или 2 цикла (Nehalem).

Дальнейшее чтение: мой ответ на What's the difference between logical SSE intrinsics?


две теории возникают мне:

  • Кто написал эту мысль, что PXOR и XORPS бы дать больше параллелизм, потому что они не конкурируют друг с другом. (Это неверно: PXOR может работать на всех портах ALU порта, но XORPS не может).

  • Это очень умный код, который специально создает задержку байпаса, чтобы избежать конфликтов ресурсов, которые могут задержать выполнение следующего PCLMULQDQ. (или, как предполагает EOF, размер кода/выравнивание может иметь какое-то отношение к нему).

Уведомление об авторских правах на код говорит «на 2011-2015 годы Intel», так что стоит рассмотреть возможность, что это как-то полезно для некоторых последних процессоров Intel, а не только на основе непонимания того, как Intel процессоров Работа. Nehalem был первым процессором, который вообще включил PCLMULQDQ, и это Intel, поэтому, если что-то будет настроено плохо на процессоры AMD. История кода не находится в git-репо, а только 6 мая, которая добавила текущую версию.

Intel whitepaper (from Dec 2009), что он основан на использовании только PXOR, а не XORPS, в его версии блока 2x pclmul/2x xor.

В таблице Agner Fog даже не отображается количество uops для PCLMULQDQ на Nehalem или какие порты они требуют. Это 12c латентность и одна на 8c пропускная способность, поэтому он может быть похож на реализацию 18-го июня Sandy/Ivybridge. Хасуэлл делает его впечатляющим 3 uops (2p0 p5), в то время как он работает только 1 uop на Broadwell (p0) и Skylake (p5).

XORPS может работать только на порту5 (до тех пор, пока Skylake не будет работать на всех трех портах ALU-порта). На Nehalem есть 2c байпасная задержка, когда один из его входов поступает от PXOR. На SnB семейства процессоров, Agner туман говорит:

В некоторых случаях, нет задержки обхода при использовании неправильного типа перетасовки или инструкции Boolean.

Так что я думаю, что нет фактически никакой дополнительной задержки байпаса для пересылки из PXOR -> XORPS на SnB, так что единственный эффект будет то, что он может работать только на порту 5. На Nehalem, это действительно может задержать XORPS до тех пор, пока не будут выполнены PSHUFB.

В основной развернутой петле есть PSHUFB после XOR, чтобы настроить входы для следующего PCLMUL. SnB/IvB может запускать целые перетасовки на p1/p5 (в отличие от Haswell, а позже, когда на p5 имеется только один блок перетасовки, но для AVX2 он имеет ширину 256b).

Поскольку конкурировать за порты, необходимые для настройки ввода для следующего PCLMUL, не кажется полезным, . Лучше всего предположить размер кода/выравнивание, если это изменение было выполнено при настройке для SnB.


На CPU, где PCLMULQDQ более 4 микрооперации, это microcoded. Это означает, что для каждого PCLMULQDQ требуется целая строка кэша uop для себя. Поскольку только 3 строки кэша uop могут сопоставляться с одним и тем же 32B-блоком инструкций x86, это означает, что большая часть кода не будет полностью входить в кеш-память на SnB/IvB. Каждая строка кэша uop может кэшировать только непрерывные инструкции. От оптимизации руководства Intel:

Все микрооперации в пути (моп строки кэша) представляют собой инструкции, которые являются статически смежными в коде и имеют свои EIPs в пределах одной и той же выровненной области 32 байт.

Это звучит как очень похожий вопрос к наличию целого числа DIV в цикле: Branch alignment for loops involving micro-coded instructions on Intel SnB-family CPUs. С правильным выравниванием, you can get it to run out of the uop cache (the DSB in Intel performance counter terminology). @Iwillnotexist Idonotexist сделал некоторое полезное тестирование на процессоре Haswell микрокодированных инструкций, показывая, что они предотвращают запуск из буфера loopback. (LSD в терминологии Intel).


На Haswell и позже, PCLMULQDQ не microcoded, так что он может идти в том же микрооперациях строки кэша с другими командами, до или после него.

Для предыдущих процессоров, возможно, стоит попытаться настроить код, чтобы нагрузить кэш uop в меньшем количестве мест. OTOH, переключение между кэшем uop и унаследованными декодерами может быть хуже, чем просто работает из декодеров.

Также IDK, если такой большой разворот действительно полезен. Вероятно, он сильно различается между SnB и Skylake, поскольку микрокодированные инструкции для конвейера очень разные, а SKL может даже не быть узким местом по пропускной способности PCLMUL.

+2

Этот код был написан для Westmere, как утверждает сам PDF. Мне кажется, что это был, вероятно, студент PhD, который написал это, и что он не ** точно знал, что он делает. Доказательство: 1. Случайное использование 'pxor/pxor' вместо' pxor/xorps'. 2. Не используйте 'mov [au] ps' для загрузки памяти. 3. Ужасный regalloc, особенно. из 'xmm10', увеличивая почти все размеры insn на 1 байт. 4. 'pclmulqdq' занимает 18 часов на Westmere, максимальная пропускная способность составляет 1 каждый 8c и кодирует w/prefixes до 7 байтов, поэтому микрооптимизации, такие как выравнивание и планирование портов, являются преждевременными. 'pxor/xorps' здесь - культ груза. –

+1

@IwillnotexistIdonotexist: hrm, да, я заметил и некоторые сомнительные распределения регистров. Но код был авторским правом 2011-2015, в то время как PDF был опубликован в 2009 году. PDF не ссылается на эту реализацию кода, поэтому вполне вероятно, что это было написано с учетом более позднего процессора. Особенно поскольку мы видим только версию 2015 года, даже версию 2011 года. Но да, это не похоже на хороший код. По-прежнему возможно, что это как-то помогает на некоторых процессорах, но я думаю, что ваша теория, вероятно, более вероятна, и это просто дерьмо. –

+1

Я в основном написал этот ответ как мыслящий мозговой свалкой, зная, что это не просто глупо. –