¿Qué consideraciones hay para predecir la latencia de las operaciones en procesadores superescalares modernos y cómo puedo calcularlas a mano?
Quiero poder predecir, a mano, exactamente cuánto tiempo aritmética arbitraria (es decir, sin ramificación o memoria, aunque eso también sería bueno) El código de ensamblaje x86-64 tomará dada una arquitectura particular, teniendo en cuenta el reordenamiento de instrucciones, la superescalaridad , latencias, IPC, etc.
¿Qué / describir las reglas se deben seguir para lograr esto?
Creo que tengo algunas reglas preliminares resueltas, pero no he podido encontrar ninguna referencia para desglosar ningún código de ejemplo a este nivel de detalle, así que tuve que hacer algunas conjeturas. (Por ejemplo, el manual de optimización de Intel apenas incluso menciona reordenamiento de instrucciones.)
Como mínimo, estoy buscando (1) confirmación de que cada regla es correcta o una declaración correcta de cada regla, y (2) una lista de cualquier regla que pueda haber olvidado.
e emiten tantas instrucciones como sea posible en cada ciclo, comenzando en orden desde el ciclo actual y potencialmente tan adelante como el tamaño del búfer de reordenamiento.e puede emitir una instrucción en un ciclo dado si: Aún no se están ejecutando instrucciones que afecten a sus operandos. Y Si se trata de una instrucción de punto flotante, cada instrucción de punto flotante antes de su emisión (las instrucciones de punto flotante tienen un reordenamiento de instrucciones estáticas). Y Hay una unidad funcional disponible para esa instrucción en ese ciclo. Cada unidad funcional (?) Está canalizada, lo que significa que puede aceptar 1 nueva instrucción por ciclo, y el número total de unidades funcionales es 1 / CPI, para el CPI de una clase de función dada (nebuloso aquí: presumiblemente, por ejemplo,addps
ysubps
usa la misma unidad funcional? ¿Cómo determino esto?). Y Menos que el ancho superescalar (generalmente4
) número de instrucciones ya se han emitido este ciclo.Si no se pueden emitir instrucciones, el procesador simplemente no emite ninguna, una condición llamada "bloqueo".Como ejemplo, considere el siguiente código de ejemplo (que calcula un producto cruzado):
shufps xmm3, xmm2, 210
shufps xmm0, xmm1, 201
shufps xmm2, xmm2, 201
mulps xmm0, xmm3
shufps xmm1, xmm1, 210
mulps xmm1, xmm2
subps xmm0, xmm1
Mi intento de predecir la latencia de Haswell se parece a esto:
; `mulps` Haswell latency=5, CPI=0.5
; `shufps` Haswell latency=1, CPI=1
; `subps` Haswell latency=3, CPI=1
shufps xmm3, xmm2, 210 ; cycle 1
shufps xmm0, xmm1, 201 ; cycle 2
shufps xmm2, xmm2, 201 ; cycle 3
mulps xmm0, xmm3 ; (superscalar execution)
shufps xmm1, xmm1, 210 ; cycle 4
mulps xmm1, xmm2 ; cycle 5
; cycle 6 (stall `xmm0` and `xmm1`)
; cycle 7 (stall `xmm1`)
; cycle 8 (stall `xmm1`)
subps xmm0, xmm1 ; cycle 9
; cycle 10 (stall `xmm0`)