O vzeroall zero registra ymm16 em ymm31?

8

A documentação para vzeroallparece inconsistente. A prosa diz:

A instrução zera o conteúdo de todos os registros XMM ou YMM.

O pseudocódigo a seguir que, contudo, indica que no modo de 64 bits única regista ymm0através ymm15são afectados:

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

Em AVX-512 máquinas de suporte de compensação até ymm15não é o mesmo que clearing "todos" porque ymm16através ymm31existir.

A prosa ou o pseudocódigo estão corretos?

BeeOnRope
fonte
5
Segundo o google, o pseudocódigo está correto. Apenas 0-15 são afetados. A implementação do bochs também diz:// clear only 16 registers even if AVX-512 is present
Jester
1
@ Jester, o manual da AMD diz o mesmo. Provavelmente relacionado a processadores com suporte ao AVX512, não é mais necessário zerar a metade superior dos registros por motivos de desempenho. Após o broadwell, o vzeroupper não era necessário (o que inclui todos os processadores AVX512). Suponho que eles decidiram não modificar o comportamento do vzeroall e vzeroupper porque o uso dessas instruções não era mais necessário nesses processadores, portanto eles estão lá principalmente por motivos herdados.
Michael Petch 24/01
1
@ MichaelPetch: o vzeroupper ainda é às vezes necessário no Skylake; a falha em usá-lo pode tornar as instruções SSE lentas (dependência falsa): Por que esse código SSE é 6 vezes mais lento sem o VZEROUPPER no Skylake? . Mas sujar ymm / zmm16..31 não pode causar esse problema porque eles estão inacessíveis com o SSE herdado. (E eu acho que não participe de transições de estados salvos que aparentemente Ice Lake reintroduziram). Além disso, a SKX tem um efeito turbo para um zmm sujo: determinando dinamicamente onde uma instrução não
Peter Cordes
2
De certa forma, o efeito de não usar vzeroupperem CPUs mais recentes pode ser muito pior devido ao efeito de mesclar uops e alargamento implícito (foi o que foi mencionado nos comentários que Peter vinculou).
BeeOnRope 24/01
1
A diferença entre os registros "alto" 16-31 e "baixo" de 0 a 15 parece ser a seguinte: a sujeira ocorre apenas com os registros baixos: colocar a CPU não é o estado superior sujo não ocorre se você escrever apenas os registros superiores . No entanto, quando você estiver no estado sujo, todos os registros serão afetados, incluindo os registros superiores. Isso é um pouco inconsistente com a minha teoria original. Minha teoria original era que o alargamento implícito não era (apenas?) Um efeito de mesclagem, porque ocorreu nas instruções AVX codificadas em VEX que não fazem nenhuma mesclagem.
BeeOnRope 25/01

Respostas:

6

Parece que foi um problema de descrição. Se você olhar o SDM mais recente , verá que a descrição foi alterada recentemente e agora diz que o VZEROALL não está alterando YMM16 ... YMM31.

Intel SDM mais recente (outubro de 2019)

Matt. Stroh
fonte
Obrigado! Eu verifiquei minha cópia do SDM, que eu geralmente mantenho bastante atualizada, mas, neste caso, não suficientemente atualizada.
BeeOnRope 27/01
1
Pesquisei um pouco no google e acho que graças ao seu Q um bug no LLVM, onde eles implementam o VZEROALL para zerar todos os registros YMM, incluindo YMM16 .., YMM31 - lists.llvm.org/pipermail/llvm-commits/Week-of-Mon -20170130 /…
Matt. Stroh
1
@ Matt.Stroh: essa mudança errada nunca chegou, ou foi revertida. Clang9.0 atuais vai usar ymm16para salvar uma __m256volta _mm256_zeroall(): godbolt.org/z/HK7_Xy . Isso só faz sentido se souber que zeroall não toca em ymm16. O clang3.9.1 é derramado na memória, então talvez ele esteja nessa versão ou talvez não seja otimizado com a mesma eficiência. Hmm, clang (3.9 e atual) não sabe que a __m128pode ser deixada em xmm0 de diâmetro _mm256_zeroupper(). godbolt.org/z/DwMyMV
Peter Cordes