Регистрирует ли vzeroall нуля от ymm16 до ymm31?

документация для vzeroall выглядит противоречивой. В прозе говорится:

Инструкция обнуляет содержимое всех регистров XMM или YMM.

Однако приведенный ниже псевдокод указывает, что в 64-битном режиме затрагиваются только регистры с ymm0 по ymm15:

IF (64-bit mode)
    limit ←15
ELSE
    limit ← 7
FOR i in 0 .. limit:
    simd_reg_file[i][MAXVL-1:0] ← 0

На машинах, поддерживающих AVX-512, очистка до ymm15 не совпадает с очисткой «всех», потому что существуют от ymm16 до ymm31.

Верна ли проза или псевдокод?


person BeeOnRope    schedule 24.01.2020    source источник
comment
Согласно google, псевдокод правильный. Только 0-15 пострадавших. Реализация Bochs также говорит: // clear only 16 registers even if AVX-512 is present   -  person Jester    schedule 24.01.2020
comment
@Jester, в руководстве AMD говорится то же самое. Вероятно, связанные с процессорами с поддержкой AVX512 больше не требуют обнуления верхней половины регистров по соображениям производительности. После Broadwell vzeroupper стал не нужен (в который входят все процессоры AVX512). Я предполагаю, что они решили не изменять поведение vzeroall и vzeroupper, потому что использование этих инструкций больше не требовалось на этих процессорах, поэтому они там в основном по устаревшим причинам.   -  person Michael Petch    schedule 24.01.2020
comment
@MichaelPetch: vzeroupper все еще иногда нужен на Skylake; отказ от его использования может замедлить выполнение инструкций SSE (ложная зависимость): Почему этот код SSE в 6 раз медленнее без VZEROUPPER на Skylake?. Но загрязнение ymm/zmm16..31 не может вызвать эту проблему, потому что они недоступны в устаревшем SSE. (И я думаю, что не участвуйте в переходах между сохраненным и верхним состоянием, которые, по-видимому, повторно ввели Ice Lake). Кроме того, SKX имеет турбо-эффект для грязного zmm: динамическое определение того, где выполняется мошенническая инструкция AVX-512   -  person Peter Cordes    schedule 24.01.2020
comment
В некотором смысле эффект от неиспользования vzeroupper на новых процессорах может быть намного хуже из-за эффекта слияния uops и неявное расширение (это то, что упоминалось в комментариях, на которые ссылался Питер).   -  person BeeOnRope    schedule 24.01.2020
comment
@BeeOnRope: механизм турборедукции расширял 128-битные операции SSE до 512 бит для слияния? Не только из-за грязного верха, просто сидящего в файле регистра при запуске чистого целочисленного кода? Я думаю, что забыл эту деталь в какой-то момент после этого, но это имеет больше смысла, учитывая, что zmm16..31 безопасно оставить грязным, а xmm/ymm16..31 можно использовать через AVX512VL без вреда для турбо. Это все есть в объяснении, которое я процитировал от вас на Полезно ли использовать VZEROUPPER, если ваша программа + библиотеки не содержат инструкций SSE?: P   -  person Peter Cordes    schedule 25.01.2020
comment
@PeterCordes - правильно, все, что использует регистры SIMD, расширяется до ширины грязных битов (может быть 256 или 512, в зависимости от типа инструкции по загрязнению). Это включает скалярный SSE FP. Если вы просто запускаете целочисленный код (и избегаете таких вещей, как rep movsb - это совсем другая тема), вы не пострадаете от эффекта и в конечном итоге получите лицензию L0.   -  person BeeOnRope    schedule 25.01.2020
comment
Разница между старшими 16-31 и младшими 0-15 регистрами выглядит так: загрязнение происходит только с младшими регистрами: установка процессора не грязного верхнего состояния не происходит, если вы записываете только верхние регистры. Однако, когда вы находитесь в грязном состоянии, это затрагивает все регистры, включая верхние регистры. Это немного противоречит моей первоначальной теории. Моя первоначальная теория заключалась в том, что неявное расширение не было (просто?) эффектом слияния, потому что оно происходило для инструкций AVX, закодированных с помощью VEX, которые не выполняют никакого слияния.   -  person BeeOnRope    schedule 25.01.2020
comment
Так что я подумал, что эти инструкции делают просто расширение нуля (в отличие от слияния): фактически каждая 128-битная или 256-битная инструкция на самом деле является 512-битной инструкцией. поскольку он устанавливает старшие биты в ноль: это проще, чем слияние, но все же влияет на все 512 бит. Однако, если бы это было правдой, почему бы вам не получить этот эффект за загрязнение верхних регистров? Они страдают той же проблемой.   -  person BeeOnRope    schedule 25.01.2020
comment
Поскольку они не уменьшают турбо, я снова предполагаю, что это эффективно обрабатывается в файле регистров или что-то в этом роде, например, 128-битная или 256-битная операция VEX просто использует 256-битные пути к ALU, а затем устанавливает в результате бит, указывающий размер, остальные считаются равными нулю. Кажется, уже есть подобные вещи для бесплатной поддержки подобных вещей в скалярных регистрах. Так что я предполагаю, что проблема с нижними регистрами действительно связана со слиянием (возможно, слияние происходит в ALU, и каждый моп получает дополнительный скрытый ввод для назначения).   -  person BeeOnRope    schedule 25.01.2020
comment
Каким-то образом это также замедляет операции, закодированные с помощью VEX, возможно, потому, что в этом сценарии активируются верхние дорожки (готовы обрабатывать слияние для не-VEX?), и это также влияет на верхние регистры.   -  person BeeOnRope    schedule 25.01.2020


Ответы (1)


Похоже, что это была проблема с описанием, если вы посмотрите на последний SDM вы увидите, что описание было недавно изменено, и теперь оно говорит что VZEROALL не меняет YMM16...YMM31.

«Последняя

person Matt. Stroh    schedule 27.01.2020
comment
Спасибо! Я проверил свою копию SDM, которую обычно обновляю, но в данном случае недостаточно. - person BeeOnRope; 28.01.2020
comment
Я немного погуглил и, думаю, благодаря вашему Q нашел ошибку в LLVM, где они реализуют VZEROALL для обнуления всех регистров YMM, включая YMM16.., YMM31 - lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20170130/ - person Matt. Stroh; 28.01.2020
comment
@ Matt.Stroh: это неправильное изменение либо так и не было внесено, либо с тех пор было отменено. Текущий clang9.0 будет использовать ymm16 для сохранения __m256 вокруг _mm256_zeroall(): godbolt.org/z/HK7_Xy. Это имеет смысл, только если известно, что zeroall не касается ymm16. clang3.9.1 действительно загружается в память, так что, возможно, он был в этой версии, или, может быть, он просто не оптимизируется так эффективно. Хм, clang (3.9 и текущие) не знает, что __m128 можно оставить в xmm0 через _mm256_zeroupper(). godbolt.org/z/DwMyMV - person Peter Cordes; 28.01.2020