Micro fusion y modos de direccionamiento
He encontrado algo inesperado (para mí) usando el Intel® Architecture Code Analyzer (IACA).
La siguiente instrucción usando [base+index]
direccionamiento
addps xmm1, xmmword ptr [rsi+rax*1]
No micro-fusible según IACA. Sin embargo, si utilizo [base+offset]
así
addps xmm1, xmmword ptr [rsi]
IACA informa que se fusiona.
La sección 2-11 del Intel optimization reference manual da el siguiente ejemplo "de micro-operaciones micro-fusionadas que pueden ser manejadas por todos decodificadores "
FADD DOUBLE PTR [RDI + RSI*8]
Y El manual de ensamblaje de optimización de Agner Fog también da ejemplos de fusión de micro-op usando [base+index]
direccionamiento. Véase, por ejemplo, la sección 12.2 "El mismo ejemplo en Core2". Entonces, ¿cuál es la respuesta correcta?
4 answers
En los decodificadores y uop-cache, el modo de direccionamiento no afecta a la micro-fusión (excepto que una instrucción con un operando inmediato no puede micro-fusionar un modo de direccionamiento relativo a RIP).
Pero algunas combinaciones de uop y modo de direccionamiento no pueden permanecer micro-fusionadas en el ROB (en el núcleo fuera de orden), por lo que las CPU de la familia SNB de Intel "no laminan" cuando es necesario, en algún momento antes de la etapa de edición/cambio de nombre. Para el rendimiento de problemas y el tamaño de ventana fuera de orden (ROB-size), cuenta de uop de dominio fusionado después de un-laminación es lo que importa.
El manual de optimización de Intel describe la des-laminación para Sandybridge en Sección 2.3.2.4: Cola de micro-op y el Detector de Flujo de Bucle (LSD), pero no describe los cambios para ninguna microarquitectura posterior.
Las reglas , lo mejor que puedo decir de los experimentos en SnB, HSW, y SKL:
- SnB (y asumo también IvB): los modos de direccionamiento indexados siempre están sin laminado, otros permanecen micro-fusionado. IACA es (en su mayoría?) correcto.
- HSW, SKL: Estos solo mantienen una instrucción ALU indexada micro-fusionada si tiene 2 operandos y trata el registro dst como lectura-modificación-escritura. Aquí "operandos" incluye banderas, lo que significa que
adc
ycmov
no micro-fusible. La mayoría de las instrucciones codificadas por VEX tampoco se fusionan ya que generalmente tienen tres operandos (así quepaddb xmm0, [rdi+rbx]
se fusiona perovpaddb xmm0, xmm0, [rdi+rbx]
no). Finalmente, la instrucción ocasional de 2 operandos donde el primer operando es write only, comopabsb xmm0, [rax + rbx]
también no se fusionen. IACA se equivoca al aplicar las reglas del SnB.
Relacionado: los modos de direccionamiento simples (no indexados) son los únicos que la unidad de dirección de tienda dedicada en el puerto 7 (Haswell y posteriores) puede manejar, por lo que todavía es potencialmente útil evitar los modos de direccionamiento indexados para las tiendas. (Un buen truco para esto es dirigirse a su dst con un solo registro, pero src con dst+(initial_src-initial_dst)
. Entonces solo tienes que incrementar el registro dst dentro de un bucle.)
Tenga en cuenta que algunas instrucciones nunca micro-fusible en absoluto (incluso en los decodificadores/uop-cache). por ejemplo, shufps xmm, [mem], imm8
, o vinsertf128 ymm, ymm, [mem], imm8
, son siempre 2 uops en SnB a través de Skylake, a pesar de que sus versiones register-source son solo 1 uop. Esto es típico para instrucciones con un operando de control imm8 más los operandos usuales dest/src1, src2 registro/memoria, pero hay algunos otros casos. por ejemplo, PSRLW/D/Q xmm,[mem]
(cuenta de desplazamiento vectorial de un operando de memoria) no micro-fusible, y tampoco PMULLD.
Ver también este post en Agner Fog blog para la discusión sobre los límites de rendimiento de problemas en HSW/SKL cuando se leen muchos registros: Mucha micro-fusión con modos de direccionamiento indexados puede conducir a ralentizaciones frente a las mismas instrucciones con menos operandos de registro: modos de direccionamiento de un registro e inmediates. Todavía no conocemos la causa, pero sospecho que hay algún tipo de límite de lectura de registros, tal vez relacionado con la lectura de muchos registros fríos del PRF.
Casos de prueba, números de real medidas : Todos estos micro-fusibles en los decodificadores, AFAIK, incluso si luego son sin-laminado.
# store
mov [rax], edi SnB/HSW/SKL: 1 fused-domain, 2 unfused. The store-address uop can run on port7.
mov [rax+rsi], edi SnB: unlaminated. HSW/SKL: stays micro-fused. (The store-address can't use port7, though).
mov [buf +rax*4], edi SnB: unlaminated. HSW/SKL: stays micro-fused.
# normal ALU stuff
add edx, [rsp+rsi] SnB: unlaminated. HSW/SKL: stays micro-fused.
# I assume the majority of traditional/normal ALU insns are like add
Instrucciones de tres entradas que HSW / SKL puede tener que des-laminar
vfmadd213ps xmm0,xmm0,[rel buf] HSW/SKL: stays micro-fused: 1 fused, 2 unfused.
vfmadd213ps xmm0,xmm0,[rdi] HSW/SKL: stays micro-fused
vfmadd213ps xmm0,xmm0,[0+rdi*4] HSW/SKL: un-laminated: 2 uops in fused & unfused-domains.
(So indexed addressing mode is still the condition for HSW/SKL, same as documented by Intel for SnB)
# no idea why this one-source BMI2 instruction is unlaminated
# It's different from ADD in that its destination is write-only (and it uses a VEX encoding)
blsi edi, [rdi] HSW/SKL: 1 fused-domain, 2 unfused.
blsi edi, [rdi+rsi] HSW/SKL: 2 fused & unfused-domain.
adc eax, [rdi] same as cmov r, [rdi]
cmove ebx, [rdi] Stays micro-fused. (SnB?)/HSW: 2 fused-domain, 3 unfused domain.
SKL: 1 fused-domain, 2 unfused.
# I haven't confirmed that this micro-fuses in the decoders, but I'm assuming it does since a one-register addressing mode does.
adc eax, [rdi+rsi] same as cmov r, [rdi+rsi]
cmove ebx, [rdi+rax] SnB: untested, probably 3 fused&unfused-domain.
HSW: un-laminated to 3 fused&unfused-domain.
SKL: un-laminated to 2 fused&unfused-domain.
Asumo que Broadwell se comporta como Skylake para adc/cmov.
Es extraño que HSW des-lamine la fuente de memoria ADC y CMOV. Tal vez Intel no llegó a cambiar eso de SnB antes de que llegaran a la fecha límite para el envío de Haswell.
La tabla de Agner insn dice cmovcc r,m
y adc r,m
no micro-fusible en absoluto en HSW/SKL, pero eso no coincide con mis experimentos. Los recuentos de ciclo que estoy midiendo coinciden con el recuento de problemas de uop de dominio fusionado, para un cuello de botella de 4 uops / reloj. Espero que vuelva a comprobarlo y corrija las tablas.
Memoria-dest entero ALU :
add [rdi], eax SnB: untested (Agner says 2 fused-domain, 4 unfused-domain (load + ALU + store-address + store-data)
HSW/SKL: 2 fused-domain, 4 unfused.
add [rdi+rsi], eax SnB: untested, probably 4 fused & unfused-domain
HSW/SKL: 3 fused-domain, 4 unfused. (I don't know which uop stays fused).
HSW: About 0.95 cycles extra store-forwarding latency vs. [rdi] for the same address used repeatedly. (6.98c per iter, up from 6.04c for [rdi])
SKL: 0.02c extra latency (5.45c per iter, up from 5.43c for [rdi]), again in a tiny loop with dec ecx/jnz
adc [rdi], eax SnB: untested
HSW: 4 fused-domain, 6 unfused-domain. (same-address throughput 7.23c with dec, 7.19c with sub ecx,1)
SKL: 4 fused-domain, 6 unfused-domain. (same-address throughput ~5.25c with dec, 5.28c with sub)
adc [rdi+rsi], eax SnB: untested
HSW: 5 fused-domain, 6 unfused-domain. (same-address throughput = 7.03c)
SKL: 5 fused-domain, 6 unfused-domain. (same-address throughput = ~5.4c with sub ecx,1 for the loop branch, or 5.23c with dec ecx for the loop branch.)
Sí, así es, adc [rdi],eax
/ dec ecx
/ jnz
ejecuta más rápido que el mismo bucle con add
en lugar de adc
en SKL. No intenté usar diferentes direcciones, ya que claramente a SKL no le gustan las reescrituras repetidas de la misma dirección (latencia de reenvío de tienda mayor de lo esperado. Ver también este post sobre la repetición de almacenar/recargar a la misma dirección siendo más lento de lo esperado en SKL.
Memory-destination adc
es tantos uops porque la familia Intel P6 (y aparentemente la familia SNB) no puede mantener las mismas entradas TLB para todos los uops de una instrucción multi-uop, por lo que necesita un uop adicional para solucionar el problema-caso donde la carga y agregar completa, y luego los errores de almacenamiento, pero el insn no se puede reiniciar simplemente porque CF ya se ha actualizado. Interesante serie de comentarios de Andy Glew (@krazyglew).
Presumiblemente la fusión en los decodificadores y la des-laminación más tarde nos salva de de necesitar microcódigo ROM para producir más de 4 uops de dominio fusionado a partir de una sola instrucción para adc [base+idx], reg
.
Por qué los un-laminados de la familia SnB :
Sandybridge simplificó el formato uop interno para ahorrar energía y transistores (junto con hacer el cambio principal al uso de un archivo de registro físico, en lugar de mantener los datos de entrada / salida en el ROB). Las CPU de la familia SnB solo permiten un número limitado de registros de entrada para un uop de dominio fusionado en el núcleo fuera de orden. Para SnB / IvB, ese límite es de 2 entradas (incluidas las banderas). Para HSW y posteriores, el límite es de 3 entradas para un uop. No estoy seguro de si el destino de memoria add
y adc
están aprovechando al máximo eso, o si Intel para sacar a Haswell de la puerta con algunas instrucciones
Nehalem y anteriores tienen un límite de 2 entradas para un uop de dominio sin fusionar, pero el ROB aparentemente puede rastrear uops micro-fusionados con 3 registros de entrada (el operando de registro sin memoria, base e índice).
Así que los almacenes indexados y las instrucciones de carga de ALU+todavía pueden decodificarse de manera eficiente (sin tener que ser el primer uop en un grupo), y no ocupan espacio adicional en la caché de uop, pero por lo demás las ventajas de la micro-fusión son esencialmente ido para afinar bucles apretados. la"des-laminación" ocurre antes del núcleo fuera de orden de 4 dominios fusionados uops por ciclo de emisión/retirada de ancho. Los contadores de rendimiento de dominio fusionado (uops_issued / uops_retired.retire_slots) contar uops de dominio fundido después de des-laminación.
La descripción de Intel del renamer (Sección 2.3.3.1: Renamer) implica que es la etapa de emisión/cambio de nombre la que realmente realiza la des-laminación, por lo que los uops destinados a la des-laminación aún pueden ser micro-fusionado en el 28/56/64 fusionado-dominio uop issue queue / loop-buffer (también conocido como el IDQ).
TODO: prueba esto. Hacer un bucle que apenas debería caber en el búfer de bucle. Cambie algo para que uno de los uops no esté laminado antes de emitirlo, y vea si todavía se ejecuta desde el búfer de bucle (LSD), o si todos los uops ahora se vuelven a recuperar desde la caché de uop (DSB). Hay contadores de perf para rastrear de dónde vienen los uops, por lo que esto debería ser fácil.
Harder TODO: si ocurre un-laminación entre la lectura de la caché de uop y la adición al IDQ, pruebe si alguna vez puede reducir el ancho de banda de la caché de uop. O si la no laminación ocurre justo en la etapa del problema, ¿puede dañar el rendimiento del problema? (es decir, cómo maneja los uops sobrantes después de emitir los primeros 4.)
(Vea la versión anterior de esta respuesta para algunas conjeturas basadas en afinar algún código LUT, con algunas notas en vpgatherdd
siendo aproximadamente 1.7 veces más ciclos que un bucle pinsrw
.)
Pruebas Experimentales en SnB
Los números HSW/SKL se midieron en un i5-4210U y un i7-6700k. Ambos tenían HT habilitado (pero el sistema inactivo por lo que el hilo tenía todo el núcleo para sí mismo). Corrí los mismos binarios estáticos en ambos sistemas, Linux 4.10 en SKL y Linux 4.8 en HSW, usando ocperf.py
. (El ordenador portátil HSW NFS-montado mi SKL desktop /home.)
Los números SnB se midieron como se describe a continuación, en un i5-2500k que ya no funciona.
Confirmado mediante pruebas con contadores de rendimiento para uops y ciclos.
Encontré una tabla de eventos PMU para Intel Sandybridge, para usar con el comando perf
de Linux. (Standard perf
desafortunadamente no tiene nombres simbólicos para la mayoría de eventos PMU específicos de hardware, como uops.) Lo utilicé para una respuesta reciente.
ocperf.py
proporciona nombres simbólicos para estos eventos PMU específicos de uarch, para que no tenga que buscar tablas. Además, el mismo nombre simbólico funciona en varios uarches. No lo estaba. consciente de ello cuando escribí esta respuesta por primera vez.
Para probar la micro-fusión uop, construí un programa de prueba que está atascado en el límite de dominio fusionado de 4 uops por ciclo de las CPU Intel. Para evitar cualquier contención de puerto de ejecución, muchos de estos uops son nop
s, que todavía se encuentran en la caché de uop y pasan por la canalización igual que cualquier otro uop, excepto que no se envían a un puerto de ejecución. (Un xor x, same
, o un movimiento eliminado, sería lo mismo.)
Programa de pruebas: yasm -f elf64 uop-test.s && ld uop-test.o -o uop-test
GLOBAL _start
_start:
xor eax, eax
xor ebx, ebx
xor edx, edx
xor edi, edi
lea rsi, [rel mydata] ; load pointer
mov ecx, 10000000
cmp dword [rsp], 2 ; argc >= 2
jge .loop_2reg
ALIGN 32
.loop_1reg:
or eax, [rsi + 0]
or ebx, [rsi + 4]
dec ecx
nop
nop
nop
nop
jg .loop_1reg
; xchg r8, r9 ; no effect on flags; decided to use NOPs instead
jmp .out
ALIGN 32
.loop_2reg:
or eax, [rsi + 0 + rdi]
or ebx, [rsi + 4 + rdi]
dec ecx
nop
nop
nop
nop
jg .loop_2reg
.out:
xor edi, edi
mov eax, 231 ; exit(0)
syscall
SECTION .rodata
mydata:
db 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
También encontré que el ancho de banda uop fuera del búfer de bucle no es una constante de 4 por ciclo, si el bucle no es un múltiplo de 4 uops. (es decir, es abc
, abc
, ...; no abca
, bcab
, ...). Desafortunadamente, el documento microarch de Agner Fog no estaba claro en esta limitación del búfer de bucle. Ver ¿Se reduce el rendimiento cuando se ejecutan bucles cuyo recuento de uop no es un múltiplo del ancho del procesador? para más investigación sobre HSW/SKL. SnB puede ser peor que HSW en este caso, pero no estoy seguro y todavía no tienen trabajo de hardware SnB.
Quería mantener la macro-fusión (comparar-y-rama) fuera de la imagen, así que usé nop
s entre el dec
y la rama. Usé 4 nop
s, por lo que con la micro-fusión, el bucle sería 8 uops, y llenar la tubería con 2 ciclos por 1 iteración.
En la otra versión del bucle, usando modos de direccionamiento de 2 operandos que no micro-fusionan, el bucle será de 10 uops de dominio fusionado, y se ejecutará en 3 ciclo.
Resultados de mi 3.3 GHz Intel Sandybridge (i5 2500k). No hice nada para que el gobernador cpufreq aumentara la velocidad del reloj antes de probar, porque los ciclos son ciclos cuando no interactúas con la memoria. He añadido anotaciones para los eventos de contador de rendimiento que tuve que introducir en hexadecimal.
Probando el modo de direccionamiento 1-reg: no cmdline arg
$ perf stat -e task-clock,cycles,instructions,r1b1,r10e,r2c2,r1c2,stalled-cycles-frontend,stalled-cycles-backend ./uop-test
Performance counter stats for './uop-test':
11.489620 task-clock (msec) # 0.961 CPUs utilized
20,288,530 cycles # 1.766 GHz
80,082,993 instructions # 3.95 insns per cycle
# 0.00 stalled cycles per insn
60,190,182 r1b1 ; UOPS_DISPATCHED: (unfused-domain. 1->umask 02 -> uops sent to execution ports from this thread)
80,203,853 r10e ; UOPS_ISSUED: fused-domain
80,118,315 r2c2 ; UOPS_RETIRED: retirement slots used (fused-domain)
100,136,097 r1c2 ; UOPS_RETIRED: ALL (unfused-domain)
220,440 stalled-cycles-frontend # 1.09% frontend cycles idle
193,887 stalled-cycles-backend # 0.96% backend cycles idle
0.011949917 seconds time elapsed
Probando el modo de direccionamiento 2-reg: con una cmdline arg
$ perf stat -e task-clock,cycles,instructions,r1b1,r10e,r2c2,r1c2,stalled-cycles-frontend,stalled-cycles-backend ./uop-test x
Performance counter stats for './uop-test x':
18.756134 task-clock (msec) # 0.981 CPUs utilized
30,377,306 cycles # 1.620 GHz
80,105,553 instructions # 2.64 insns per cycle
# 0.01 stalled cycles per insn
60,218,693 r1b1 ; UOPS_DISPATCHED: (unfused-domain. 1->umask 02 -> uops sent to execution ports from this thread)
100,224,654 r10e ; UOPS_ISSUED: fused-domain
100,148,591 r2c2 ; UOPS_RETIRED: retirement slots used (fused-domain)
100,172,151 r1c2 ; UOPS_RETIRED: ALL (unfused-domain)
307,712 stalled-cycles-frontend # 1.01% frontend cycles idle
1,100,168 stalled-cycles-backend # 3.62% backend cycles idle
0.019114911 seconds time elapsed
Entonces, ambas versiones ejecutaron instrucciones de 80M, y enviaron uops de 60M a los puertos de ejecución. (or
con una fuente de memoria envía a una ALU para el or
, y un puerto de carga para la carga, independientemente de si estaba micro-fusionada o no en el resto de la tubería. nop
no envía a un puerto de ejecución en absoluto.) Del mismo modo, ambas versiones retiran 100M uops de dominio sin fusionar, porque los 40M nops cuentan aquí.
La diferencia está en los contadores para el dominio fusionado.
- La versión de dirección de 1 registro solo emite y retira uops de dominio fusionado de 80M. Este es el mismo que el número de instrucciones. Cada insn se convierte en un uop de dominio fusionado.
- La versión de 2 direcciones de registro emite 100M uops de dominio fusionado. Este es el mismo que el número de uops de dominio sin fusionar, lo que indica que no se produjo una micro-fusión.
Sospecho que solo verá una diferencia entre UOPS_ISSUED y UOPS_RETIRED(ranuras de retiro utilizado) si los errores de la rama llevaron a uops ser cancelado después de la emisión, pero antes de la jubilación.
Y finalmente, el impacto en el rendimiento es real. La versión no fusionada tomó 1,5 veces más ciclos de reloj. Esto exagera la diferencia de rendimiento en comparación con la mayoría de los casos reales. El bucle tiene que ejecutarse en un número entero de ciclos, y los 2 uops adicionales lo empujan de 2 a 3. A menudo, un uops de dominio fusionado adicional de 2 hará menos diferencia. Y potencialmente no hay diferencia, si el código es embotellado por algo que no sea 4-fusionado-dominio-uops-por-ciclo.
Aún así, el código que hace muchas referencias de memoria en un bucle podría ser más rápido si se implementa con una cantidad moderada de desenrollamiento e incremento de múltiples punteros que se utilizan con un direccionamiento simple [base + immediate offset]
, en lugar de usar los modos de direccionamiento [base + index]
.
Cosas posteriores
RIP-relative with an immediate can't micro-fuse . Las pruebas de Agner Fog muestran que este es el caso incluso en el decodificadores / uop-caché, por lo que nunca se fusionan en el primer lugar (en lugar de ser un-laminado).
IACA se equivoca, y afirma que ambos micro-fusibles: {[62]]}
cmp dword [abs mydata], 0x1b ; fused counters != unfused counters (micro-fusion happened, and wasn't un-laminated). Uses 2 entries in the uop-cache, according to Agner Fog's testing
cmp dword [rel mydata], 0x1b ; fused counters ~= unfused counters (micro-fusion didn't happen)
RIP-rel hace micro-fusible (y permanecer fusible) cuando no hay inmediato, por ejemplo:
or eax, dword [rel mydata] ; fused counters != unfused counters, i.e. micro-fusion happens
La micro-fusión no aumenta la latencia de una instrucción. La carga puede emitirse antes de que la otra entrada esté lista.
ALIGN 32
.dep_fuse:
or eax, [rsi + 0]
or eax, [rsi + 0]
or eax, [rsi + 0]
or eax, [rsi + 0]
or eax, [rsi + 0]
dec ecx
jg .dep_fuse
Este bucle se ejecuta a 5 ciclos por iteración, debido a la eax
cadena dep. No más rápido que una secuencia de or eax, [rsi + 0 + rdi]
, o mov ebx, [rsi + 0 + rdi] / or eax, ebx
. (Las versiones no fusionadas y mov
ejecutan el mismo número de uops.) Scheduling / dep checking sucede en el dominio unfused. Los uops recién emitidos entran en el planificador (también conocido como Reservation Station (RS)), así como en el ROB. Dejan el planificador después de enviar (también conocido como ser enviado a una unidad de ejecución), pero permanecen en el ROBO hasta la jubilación. Por lo tanto, la ventana fuera de orden para ocultar la latencia de carga es al menos el tamaño del planificador (54 uops de dominio sin fusionar en Sandybridge, 60 en Haswell, 97 en Skylake).
Micro-fusion no tiene un atajo para la base y el desplazamiento siendo el mismo registro. Un bucle con or eax, [mydata + rdi+4*rdi]
(donde rdi se pone a cero) ejecuta tantos uops y ciclos como el bucle con or eax, [rsi+rdi]
. Este modo de direccionamiento podría usarse para iterar sobre una matriz de estructuras de tamaño impar que comienzan en una dirección fija. Esto probablemente nunca se usa en la mayoría de los programas, por lo que no es sorprendente que Intel no gastara transistores al permitir que este caso especial de modos de 2 registros se microfusione. (E Intel lo documenta como" modos de direccionamiento indexados " de todos modos, donde se necesita un factor de registro y escala.)
Macro-fusión de un cmp
/jcc
o dec
/jcc
crea un uop que permanece como un solo uop incluso en el ciclo-dominio. dec / nop / jge
todavía se puede ejecutar en un solo ciclo, pero es de tres uops en lugar de uno.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-18 18:55:54
Nota: Desde que escribí esta respuesta, Peter probó Haswell y Skylake también e integró los resultados en la respuesta aceptada anteriormente (en particular, la mayoría de las mejoras que atribuyo a Skylake a continuación parecen haber aparecido en Haswell). Deberías ver esa respuesta para el resumen del comportamiento en las CPU y esta respuesta (aunque no es incorrecta) es principalmente de interés histórico.
Mi prueba indica que en Skylake al menos 1 , el procesador fusiona completamente incluso modos de direccionamiento complejos, a diferencia de Sandybridge.
Es decir, las versiones 1-arg y 2-arg del código publicado anteriormente por Peter se ejecutan en el mismo número de ciclos, con el mismo número de uops enviados y retirados.
Mis resultados:
Estadísticas de contador de rendimiento para ./uop-test
:
23.718772 task-clock (msec) # 0.973 CPUs utilized
20,642,233 cycles # 0.870 GHz
80,111,957 instructions # 3.88 insns per cycle
60,253,831 uops_executed_thread # 2540.344 M/sec
80,295,685 uops_issued_any # 3385.322 M/sec
80,176,940 uops_retired_retire_slots # 3380.316 M/sec
0.024376698 seconds time elapsed
Estadísticas de contador de rendimiento para ./uop-test x
:
13.532440 task-clock (msec) # 0.967 CPUs utilized
21,592,044 cycles # 1.596 GHz
80,073,676 instructions # 3.71 insns per cycle
60,144,749 uops_executed_thread # 4444.487 M/sec
80,162,360 uops_issued_any # 5923.718 M/sec
80,104,978 uops_retired_retire_slots # 5919.478 M/sec
0.013997088 seconds time elapsed
Estadísticas de contador de rendimiento para ./uop-test x x
:
16.672198 task-clock (msec) # 0.981 CPUs utilized
27,056,453 cycles # 1.623 GHz
80,083,140 instructions # 2.96 insns per cycle
60,164,049 uops_executed_thread # 3608.645 M/sec
100,187,390 uops_issued_any # 6009.249 M/sec
100,118,409 uops_retired_retire_slots # 6005.112 M/sec
0.016997874 seconds time elapsed
No encontré ninguna UOPS_RETIRED_ANY instrucción en Skylake, solo el tipo" ranuras retirados " que es aparentemente fusionada-dominio.
La prueba final (uop-test x x
) es una variante que Peter sugiere que usa un RIP-relative cmp
con immediate, que no se sabe que microfuse:
.loop_riprel
cmp dword [rel mydata], 1
cmp dword [rel mydata], 2
dec ecx
nop
nop
nop
nop
jg .loop_riprel
Los resultados muestran que los 2 uops adicionales por ciclo son recogidos por los contadores uops emitidos y retirados (por lo tanto, la prueba puede diferenciar entre fusión que ocurre y no).
Más pruebas en otras arquitecturas son ¡bienvenido! Puedes encontrar el código (copiado de Peter arriba) en github .
[1] ... y quizás algunas otras arquitecturas entre Skylake y Sandybridge, ya que Peter solo probó SB y yo solo probé SKL.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-18 02:42:39
Los procesadores Intel más antiguos sin caché uop pueden hacer la fusión, así que tal vez esto sea un inconveniente de la caché uop. No tengo tiempo para probar esto ahora, pero agregaré una prueba para uop fusion la próxima vez que actualice mis scripts de prueba . ¿Has intentado con las instrucciones de FMA? Son las únicas instrucciones que permiten 3 dependencias de entrada en una uop no fusionada.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-12 05:49:16
Ahora he revisado los resultados de las pruebas de Intel Sandy Bridge, Ivy Bridge, Haswell y Broadwell. No he tenido acceso a la prueba en un Skylake todavía. Los resultados son:
- Las instrucciones con direccionamiento de dos registros y tres dependencias de entrada se están fusionando perfectamente. Solo toman una entrada en la caché de micro-operación siempre y cuando no contengan más de 32 bits de datos (o 2 * 16 bits).
- Es posible hacer instrucciones con cuatro dependencias de entrada, usando fusionado instrucciones de multiplicar y agregar en Haswell y Broadwell. Estas instrucciones aún se fusionan en un solo micro-op y solo toman una entrada en el caché de micro-op.
- Las instrucciones con más de 32 bits de datos, por ejemplo, la dirección de 32 bits y los datos inmediatos de 8 bits aún pueden fusionarse, pero usan dos entradas en la caché de microoperaciones (a menos que los 32 bits se puedan comprimir en un entero con signo de 16 bits)
- Las instrucciones con direccionamiento relativo rip y una constante inmediata no se fusionan, incluso si tanto el desplazamiento como la constante inmediata son muy pequeños.
- Todos los resultados son idénticos en las cuatro máquinas analizadas.
- Las pruebas se realizaron con mis propios programas de prueba utilizando los contadores de monitoreo de rendimiento en bucles que eran lo suficientemente pequeños como para caber en la caché de micro-op.
Sus resultados pueden deberse a otros factores. No he intentado usar la IACA.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-01 14:54:01