¿Vzeroall cero registra ymm16 a ymm31?

8

La documentación para vzeroallparece inconsistente. La prosa dice:

La instrucción pone a cero el contenido de todos los registros XMM o YMM.

El pseudocódigo debajo de eso, sin embargo, indica que en el modo de 64 bits sólo registra ymm0a través ymm15afectados:

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

En AVX-512 máquinas de soporte de compensación hasta ymm15que no es el mismo que el de compensación "todos" porque ymm16a través de ymm31existir.

¿Es correcta la prosa o el seudocódigo?

BeeOnRope
fuente
55
Según Google, el pseudocódigo es correcto. Solo 0-15 se ven afectados. La implementación de Bochs también dice:// clear only 16 registers even if AVX-512 is present
Bufón
1
@Jester, el manual de AMD dice lo mismo. Probablemente relacionado con procesadores con soporte AVX512 ya no requieren poner a cero la mitad superior de los registros por razones de rendimiento. Después de Broadwell vzeroupper no era necesario (que incluye todos los procesadores AVX512). Supongo que decidieron no modificar el comportamiento de vzeroall y vzeroupper porque el uso de estas instrucciones ya no era necesario en estos procesadores, por lo que están allí por razones heredadas en su mayoría.
Michael Petch
1
@MichaelPetch: vzeroupper todavía se necesita a veces en Skylake; Si no lo usa, las instrucciones SSE pueden ser lentas (dependencia falsa): ¿Por qué este código SSE es 6 veces más lento sin VZEROUPPER en Skylake? . Pero ensuciar ymm / zmm16..31 no puede causar ese problema porque son inaccesibles con SSE heredado. (Y creo que no participe en las transiciones de estado superiores guardadas que aparentemente Ice Lake reintrodujo). Además, SKX tiene un efecto turbo para un zmm sucio: determinar dinámicamente dónde se está ejecutando una instrucción AVX-512
Peter Cordes
2
De alguna manera, el efecto de no usar vzeroupperen las CPU más nuevas puede ser mucho peor debido al efecto de fusionar uops y ensanchamiento implícito (eso es lo que se mencionó en los comentarios que Peter vinculó).
BeeOnRope
1
La diferencia entre los registros 0-15 "alto" 16-31 y "bajo" parece ser así: la suciedad solo ocurre con los registros bajos: poner la CPU no es el estado superior sucio no ocurre si solo escribe registros superiores . Sin embargo, una vez que esté en estado sucio, todos los registros se verán afectados, incluidos los registros superiores. Esto es un poco inconsistente con mi teoría original. Mi teoría original era que el ensanchamiento implícito no era (¿solo?) Un efecto de fusión, porque sucedió con instrucciones AVX codificadas por VEX que no se fusionan.
BeeOnRope

Respuestas:

6

Parece que fue un problema de descripción, si observa el último SDM , verá que la descripción se modificó últimamente y ahora dice que VZEROALL no cambia YMM16 ... YMM31.

Intel SDM más reciente (octubre de 2019)

Mate. Stroh
fuente
¡Gracias! Verifiqué mi copia de SDM, que generalmente mantengo bastante actualizada, pero en este caso no lo suficientemente actualizada.
BeeOnRope
1
Busqué en Google un bit, y creo que encontré gracias a tu Q un error en LLVM donde implementan VZEROALL para poner a cero todos los registros de YMM, incluidos YMM16 .., YMM31 - lists.llvm.org/pipermail/llvm-commits/Week-of-Mon -20170130 / ...
Matt. Stroh
1
@ Matt.Stroh: ese cambio incorrecto nunca se logró o desde entonces se ha revertido. El clang9.0 actual se usará ymm16para salvar un __m256entorno _mm256_zeroall(): godbolt.org/z/HK7_Xy . Eso solo tiene sentido si sabe que zeroall no toca ymm16. clang3.9.1 se derrama en la memoria, por lo que tal vez estaba en esa versión, o tal vez simplemente no se optimiza tan eficientemente. Hmm, clang (3.9 y actual) no sabe que __m128se puede dejar un xmm0 de ancho _mm256_zeroupper(). godbolt.org/z/DwMyMV
Peter Cordes