Запись в регистр ZMM может привести к тому, что процессор Skylake-X (или аналогичный) может бесконечно долго находиться в состоянии пониженного макс-турбо. ( SIMD-инструкции, понижающие частоту процессора и Динамическое определение того, где выполняется мошенническая инструкция AVX-512 ) Предположительно, Ice Lake похож.
( Обходной путь: нетпроблема для zmm16..31 , согласно комментариям @ BeeOnRope, которые я цитировал в Полезно ли использовать VZEROUPPER, если ваша программа + библиотеки не содержат инструкций SSE? Так что этот strlen может просто использовать vpxord xmm16,xmm16,xmm16
и vpcmpeqb
с zmm16.)
Как проверить это, если у вас есть оборудование:
@ BeeOnRope опубликовал тестовый код в потоке RWT : заменить vbroadcastsd zmm15, [zero_dp]
с vpcmpeqb k0, zmm0, [rdi]
в качестве команды «загрязнения» и посмотрите, будет ли цикл после этого медленным или быстрым.
Я предполагаю, что выполнение любого 512-битного мопа временно вызовет пониженное турбо (наряду с отключением порта1 для векторных ALU-мопов, в то время как 512-битный моп фактически находится на заднем плане), но вопрос в следующем: восстановится ли ЦП самостоятельно, если вы никогда не будете использовать vzeroupper
после всего лишь чтения ZMMрегистр?
(И / или будут ли последующие инструкции SSE или AVX иметь штрафы за переход или ложные зависимости?)
В частности, strlen
, использующему такие insns, нужно vzeroupper
перед возвратом? (На практике на любом реальном процессоре и / или в соответствии с документацией Intel для получения рекомендаций на будущее.) Предположим, что более поздние инструкции могут включать не VEX SSE и / или кодировку VEX AVX1 / 2, а нетолько целое число GP, в случае, если это имеет отношение к ситуации «грязный верхний-256», сохраняющей турбо сокращение.
; check 64 bytes for zero, strlen building block.
vpxor xmm0,xmm0,xmm0 ; zmm0 = 0 using AVX1 implicit zero-extension
vpcmpeqb k0, zmm0, [rdi] ; 512-bit load + ALU, not micro-fused
;kortestq k0,k0 / jnz or whatever
kmovq rax, k0
tzcnt rax, rax
;vzeroupper before lots of code that goes a long time before another 512-bit uop?
(Вдохновленный strlen в AVX512BW: обрабатывать 64-битную маску в 32-битном кодес bsf / tzcnt? , который выглядел бы так, если бы обнуление его вектора reg было должным образом оптимизировано для использования более короткого VEX вместо инструкции EVEX.)
Ключевой инструкцией является vpcmpeqb k0, zmm0, [rdi]
, котораядекодирует в SKX или CNL до 2 отдельных мопов ( без микросинхронизации: retire-slots = 2.0 ): 512-битная загрузка (в 512-битный физический регистр?) и сравнение ALU в маскезарегистрируйтесь.
но нет архитектурный Регистр ZMM всегда записывается явно, только для чтения. Таким образом, предположительно, по крайней мере, xsave
/ xrstor
очистит любое «грязное верхнее» условие, если оно существует после этого. (Это не произойдет в Linux, если нет фактического переключения контекста на другой процесс пользовательского пространства на этом ядре или поток мигрирует; простой ввод в ядро для прерываний не вызовет его. Так что это на самом деле все еще тестируется подосновная ОС, если у вас есть оборудование; у меня нет.)
Возможности, которые я могу представить для SKX / CNL и / или Ice Lake:
- Нет долгосрочного эффекта: max-turbo восстанавливается так же быстро, как и с
vzeroupper
- Макс. Turbo ограничивается 512-битной скоростью до переключения контекста. (
xrstor
или эквивалентный снимает любой флаг состояния «грязный верхний», потому что архитектурные регистры чистые). - Максимальное турбо ограничение ограничено 512-битной скоростью даже при переключении контекста, как если бы вы запускали
vaddps zmm0,zmm0,zmm0
,(Грязный верхний флаг устанавливается в сохраненном и восстановленном в архитектурном состоянии.) Вероятно, потому что xsaveopt
пропускает сохранение верхних 128 или 256 векторных регистров, если известно, что они чистые.
Полагаю, kmovq
не уменьшит максимальное турбо или не вызовет другие 512-битные эффекты UOP. Старшие 32 бита регистров маски обычно вступают в игру с AVX512BW только для 64-байтовых векторов, но, по-видимому, они не обеспечивают питание верхних 32 битов регистров маски отдельно, только верхние 32 байта векторных рег. Существуют варианты использования, например, использование kshift
или kunpack
для работы с 64-битными порциями масок (для загрузки / сохранения или передачи в целочисленные регистры), даже если вы только когда-либо генерируете или используете их 32 битами одновременно с AVX512VLс рег. YMM или XMM
PS: Xeon Phi не подвержен этим эффектам;он не предназначен для работы выше тяжелого AVX512 при запуске другого кода, потому что он создан для запуска AVX512. И на самом деле vzeroupper
очень медленный и не рекомендуется для KNL / KNM.
Тот факт, что мой пример использует AVX512BW, действительно не имеет отношения к вопросу, но все основные (не Xeon Phi) процессоры с AVX512 имеютAVX512BW. Это просто хороший пример реального использования, и тот факт, что использование AVX512BW исключает KNL, не имеет значения.