Есть ли разница в производительности между AVX-512 `_mm512_load_epi64` и `_mm512_loadu_epi64`?

Мотивация этого вопроса

Невыровненная нагрузка обычно используется чаще. Разработчик должен использовать выровненную загрузку SIMD, когда адрес уже выровнен. Поэтому я начал задаваться вопросом, есть ли какая-то разница в производительности между этими двумя вызовами функций по уже выровненному адресу. Интуитивное предположение состоит в том, что выровненная загрузка быстрее, чем невыровненная загрузка.

Я знаю, что этот вопрос может быть очень аппаратно-зависимым. Еще одна мотивация заключается в том, что Zen4 — это первая микроархитектура AMD, предлагающая AVX-512, поэтому я хочу попробовать AVX-512 на Zen4 и посмотреть результаты.

Код бенчмарка и сборка

Код: https://godbolt.org/z/W3qvcjGWs

Я оцениваю два случая:

  • Первый случай: я гарантирую, что память, к которой осуществляется доступ data, имеет размер меньше, чем кэш L1. Так что у меня нет промахов кеша; поэтому не привязан к памяти.
  • Второй случай: доступная память больше кэша. Единственная разница между вызовами функций в ассемблере: vmovdqa64 и vmovdqu64.

Результат

Мой эксперимент проводился на AMD Zen4. Я тестировал вызов функции десять раз. Результат непротиворечив, и оказывается, что эти два вызова функций одинаково быстры. Это противоречит моей интуиции. Если это правда, то нет варианта использования фактической выровненной нагрузки, которая имеет минимальный сценарий и приводит к seg-fault на невыровненном адресе.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Нет недостатка в выровненных данных

Если память выровнена (чтобы load могла работать, а не выдавать ошибку), производительность идентична. Процессоры Intel и AMD были такими со времен Nehalem и K10. (Или бульдозер для movdqu хранилищ также работает так же, как требуется выравнивание, когда данные выровнены.)

Это не изменилось с 512-битными векторами, _mm512_loadu_si512 быстро работает с выровненными данными.

Если ваши данные обычно выровнены, невыровненные загрузки — отличный выбор; нет дополнительных инструкций, проверяющих выравнивание для общего случая, и аппаратное обеспечение справляется с этим не так уж ужасно в редких случаях. Если вы хотите с шумом обнаружить, что данные когда-либо смещены, используйте выровненные загрузки (и компилируйте с помощью GCC или clang, а не MSVC или ICC, которые никогда не используют требуемые для выравнивания загрузки/сохранения в asm).

Чтобы фактически протестировать несовпадение, вам может потребоваться отключить оптимизацию (при очень высокой производительности кода), если компилятор складывает ваши встроенные функции загрузки в операнды источника памяти для других инструкций. Проверка ожиданий выравнивания — это прецедент для vmovdqa64 и друзей.


Если ваши данные на самом деле большую часть времени смещены, для 256-битных векторов все еще может быть нормально, чтобы ЦП обрабатывал их. (Остерегайтесь Почему gcc не разрешает _mm256_loadu_pd как одиночный vmovupd? с настройкой GCC по умолчанию до GCC11). Возможно, стоит иметь дополнительный код, который должен запускаться каждый раз, когда проверяется выравнивание и, возможно, делает невыровненный первый вектор, возможно, перекрывающийся с первым выровненным вектором, если с вашей операцией SIMD все в порядке.

См. Как точно определить скорость невыровненного доступа на x86_64? некоторые подробности о влиянии на производительность и Каков фактический эффект успешных невыровненных обращений к x86?.


Смещенные 512-битные векторы очень медленные

Интересная особенность 512-битных векторов заключается в том, что любое несовпадение обязательно означает разделение строки кэша, невозможное смещение, но все же содержащееся в одной 64-байтовой строке кэша, как для 16-байтовых и 32-байтовых векторов. (В этих случаях Intel, начиная с Haswell, и AMD, начиная с Zen 2 или 3, я думаю (?) по-прежнему имеют полную производительность для невыровненной загрузки/сохранения.) См. https://uops.info/ и https:// agner.org/оптимизировать/

По крайней мере, для процессоров Intel выравнивание ваших данных весьма полезно для AVX-512, даже если ваш код ограничивает пропускную способность DRAM; явно невыровненные 64-байтовые загрузки, которые на самом деле смещаются во время выполнения, приводят к снижению пропускной способности памяти на ядро, примерно на 15%, по сравнению с всего парой процентов для кода, использующего 256-битные векторы, если это так.

64-байтовые невыровненные загрузки обычно () выполняются с одной загрузкой за цикл на процессорах SKX/CLX — эффективно используя оба интерфейса чтения 64-байтного кэша L1D для захвата последовательных строк кэша, а затем сдвиг/объединение результатов в 512-битный пункт назначения регистр. По причинам, которые не совсем ясны, даже этот штраф в 1/2 цикла приводит к значительному падению пропускной способности для данных, расположенных дальше в иерархии памяти... () Существует больший штраф за невыровненные загрузки, которые пересекают страницу. граница.

John D McCalpin 13.12.2022 17:38

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