¿Cómo puede una CPU entregar más de una instrucción por ciclo?

41

La página de instrucciones por segundo de Wikipedia dice que un i7 3630QM entrega ~ 110,000 MIPS a una frecuencia de 3.2 GHz; sería (110 / 3.2 instrucciones) / 4 núcleos = ~ 8.6 instrucciones por ciclo por núcleo ?! ¿Cómo puede un solo núcleo entregar más de una instrucción por ciclo?

Según tengo entendido, una tubería solo debería poder entregar un resultado por reloj.

Estos son mis pensamientos:

  • La frecuencia interna es en realidad superior a 3.2 GHz
  • Algunas partes de la CPU son asíncronas de una manera que un humano humilde como yo no puede entender
  • Hay múltiples tuberías concurrentes por núcleo
  • Una tubería puede entregar más que el resultado por reloj, una instrucción puede omitir las etapas de la tubería y hay múltiples captadores previos para mantenerse al día
  • Me falta algo
sin trabajo
fuente
1
Ofrece 110,000 Dhrystone MIPS, por lo que DMIPS, no MIPS, es algo que veo directamente, ¿tal vez esto podría marcar la diferencia? Ver en.wikipedia.org/wiki/Dhrystone

Respuestas:

44

Primero, como lo señalan el comentario de Keelan y la respuesta de Turbo J , la medición fue de 113,093 MIPS Dhrystone, no MIPS nativos .

La microarquitectura Ivy Bridge del i7 3630QM solo puede comprometer 4 µops fusionados por ciclo, aunque puede comenzar la ejecución de 6 µops por ciclo. (El número de µops fusionados en una traza de código es aproximadamente igual al número de instrucciones; algunas instrucciones complejas se decodifican en múltiples µops que no están fusionadas y algunos pares de instrucciones pueden fusionarse en una sola µop, por ejemplo, una comparación inmediata seguido de un salto condicional).

Dos de sus especulaciones sobre cómo se pueden ejecutar múltiples instrucciones en un solo ciclo son bastante válidas y se han utilizado en procesadores reales. Su primera especulación, que se utiliza un reloj interno más rápido, se utilizó en las ALU "bola de fuego" del Pentium 4 original. Estas ALU se registraron al doble de la frecuencia del resto del núcleo, que ya era relativamente alta.

(Esto se logró mediante el uso de una ALU escalonada en la que la mitad inferior de una adición se realizó en un ciclo, lo que permite que una operación dependiente use la mitad inferior del resultado en el siguiente ciclo. Para operaciones como sumar, xor o desplazamiento a la izquierda que solo necesitan la mitad inferior de los operandos para producir la mitad inferior completa del resultado, tal escalonamiento, también conocido como canalización de ancho, permite una latencia de resultados de ciclo único, así como un rendimiento de ciclo único).

HyperSPARC utilizó una técnica algo relacionada, las ALU en cascada. HyperSPARC introdujo los resultados de dos ALU en una tercera ALU. Esto permitió ejecutar dos operaciones independientes y una tercera dependiente en un solo ciclo.

Su especulación de que "hay múltiples tuberías concurrentes por núcleo" es la otra técnica que se ha utilizado. Este tipo de diseño se llama superescalar y es, con mucho, el medio más común para aumentar el número de operaciones ejecutadas en un solo ciclo.

También hay algunas otras probabilidades y fines de ejecución de la instrucción que vale la pena señalar. Algunas operaciones pueden realizarse de manera más eficiente fuera de las unidades de ejecución ordinarias. La técnica de eliminación de movimientos explota el uso del cambio de nombre de registro en procesadores fuera de orden para realizar operaciones de movimiento durante el cambio de nombre de registro; el movimiento simplemente copia el número de registro físico de una posición en la tabla de cambio de nombre (llamada tabla de alias de registro) a otra. Esto no solo aumenta efectivamente el ancho de ejecución sino que también elimina una dependencia. Esta técnica se utilizó antes con el x87 basado en pila, pero ahora se usa ampliamente en los procesadores x86 de alto rendimiento de Intel. (El uso de instrucciones destructivas de dos operandos en x86 hace que la eliminación de movimientos sea más útil de lo que sería en un RISC típico).

Una técnica similar a la eliminación de movimiento es el manejo de las instrucciones de puesta a cero del registro durante el cambio de nombre. Al proporcionar un nombre de registro que proporcione el valor cero, una instrucción de borrado de registro (como xor o restar con ambos operandos siendo el mismo registro) simplemente puede insertar ese nombre en la tabla de cambio de nombre (RAT).

Otra técnica utilizada por algunos procesadores x86 reduce el costo de las operaciones push y pop. Normalmente, una instrucción que usa el puntero de la pila tendría que esperar un ciclo completo para una inserción o pop anterior para actualizar el valor del puntero de la pila. Al reconocer que push y pop solo suman o restan un pequeño valor al puntero de la pila, uno puede calcular los resultados de múltiples adiciones / subtacciones en paralelo. El retraso principal para la adición es la propagación de acarreo, pero con valores pequeños, los bits más significativos del valor base, en este caso el puntero de la pila, solo tendrán como máximo un arrastre. Esto permite que se aplique una optimización similar a la de un sumador carry-select a múltiples adiciones de valores pequeños. Además, dado que el puntero de la pila generalmente solo se actualiza mediante constantes,

También es posible fusionar instrucciones en una sola operación más compleja. Si bien el proceso inverso de dividir las instrucciones en operaciones múltiples y más simples es una técnica antigua, fusionar instrucciones (que Intel denomina fusión macro-op) puede permitir que la implementación admita operaciones más complejas que las expuestas en el conjunto de instrucciones.

En el lado teórico, se han propuesto otras técnicas. Las constantes pequeñas que no sean cero podrían admitirse en la RAT y algunas operaciones simples que usan o producen de manera confiable valores tan pequeños podrían manejarse temprano. ("Physical Register Inlining", Mikko H. Lipasti et al., 2004, sugirió usar la RAT como un medio para reducir el conteo de registros, pero la idea podría extenderse para soportar la carga de pequeños elementos inmediatos y operaciones simples en números pequeños).

Para las memorias caché de rastreo (que almacenan secuencias de instrucciones bajo supuestos particulares de flujo de control), puede haber oportunidades para fusionar operaciones separadas por ramas y eliminar operaciones que producen resultados no utilizados en la traza. El almacenamiento en caché de las optimizaciones en una memoria caché de seguimiento también puede alentar la realización de optimizaciones, como la fusión de instrucciones, que tal vez no valga la pena si se tuvieran que hacer cada vez que se obtiene la secuencia de instrucciones.

La predicción de valor se puede usar para aumentar el número de operaciones que se pueden ejecutar en paralelo eliminando dependencias. Un predictor de valor basado en pasos es similar a la optimización pop / push de un motor de pila especializado mencionado anteriormente. Puede calcular múltiples adiciones principalmente en paralelo, eliminando la serialización. La idea general de la predicción de valor es que con un valor predicho, las operaciones dependientes pueden proceder sin demora. (La dirección de la bifurcación y la predicción del objetivo es efectivamente solo una forma muy limitada de predicción de valor, que permite obtener las siguientes instrucciones que dependen del "valor" de la bifurcación, tomada o no, y la siguiente dirección de instrucción, otro valor).

Paul A. Clayton
fuente
¡increíble! Gracias por la valiosa información. ¿Podría sugerirme un libro donde pueda leer todas estas técnicas arquitectónicas?
trabajo el
@workless Una vez que vaya más allá de los conceptos básicos de canalización y ejecución superescalar fuera de orden (que estaría cubierto por la mayoría de los libros de texto de arquitectura de computadoras), las mejores fuentes de información son probablemente descripciones de microarquitecturas de procesador específicas (como el artículo sobre Haswell vinculado en la respuesta de gnasher729 ) y trabajos académicos (ISCA y MICRO [conferencias] generalmente tienen buenos trabajos; HPCA, PACT, ASPLOS, y quizás algunos otros también tienen buena reputación). Andy Glew (quizás el más famoso por su trabajo en el Pentium Pro) ...
Paul A. Clayton
1
... estaba trabajando en una wiki de CompArch, que presentaría conceptos más avanzados, pero el progreso fue lento y aparentemente fue pirateado hace un tiempo, por lo que ahora solo muestra un mensaje de error ( semipublic.comp-arch.net/wiki ). Tiene la intención de restablecer el wiki (se ha preservado el texto original) usando un software wiki diferente (tuvo algunos problemas con el software que estaba usando y está tomando esto como una oportunidad para hacer mejoras), pero "será un tiempo".
Paul A. Clayton
Un buen ejemplo del éxito de la arquitectura superescalar fue el HyperThreading de Intel: con todas esas optimizaciones, los ingenieros de Intel descubrieron que aproximadamente el 30% de la ALU no se usaba la mayor parte del tiempo, porque la memoria no puede fluir lo suficientemente rápido o la tubería no se puede llenar de manera suficientemente eficiente. HyperThreading le permite obtener mucho trabajo gratis en el escenario ideal. Es mucho menos que tener un nuevo núcleo separado, pero también es mucho más barato (y también se puede combinar con varios núcleos).
Luaan
@ PaulA.Clayton: dos capturas de esa página están en Wayback. 20 de diciembre de 2013 y 14 de febrero de 2014 . No sé si esas capturas son anteriores a los problemas con la página. Desafortunadamente, cuando intenté visitar esas páginas en Wayback, recibí el mensaje " Bummer. La máquina que sirve este archivo está inactiva. Estamos trabajando en ello ", así que no estoy seguro de lo que se puede ver en esas páginas. .
Kevin Fegan
10

Un poco de magia oscura ocurre en el interior de los procesadores modernos, pero sus pensamientos definitivamente están en la línea correcta.

La clave para comprender la eficiencia de los procesadores modernos es darse cuenta de que son superescalares . De Wikipedia (énfasis mío):

Una arquitectura de CPU superescalar implementa una forma de paralelismo llamada paralelismo a nivel de instrucción dentro de un único procesador. Por lo tanto, permite un rendimiento de CPU más rápido de lo que sería posible a una velocidad de reloj dada.

Estos procesadores modernos tienen múltiples unidades de ejecución por núcleo, como habrás adivinado. Hyper-threading es interesante considerar, se duplican algunas partes de la tubería, pero algunos no lo son.

También es interesante leer acerca de la ejecución fuera de orden , pero no responde directamente a su pregunta. Sin embargo, reduce el número de ciclos de CPU "desperdiciados".

La eficiencia también se ve afectada por muchas otras cosas que pueden causar un bloqueo dentro del procesador, que incluyen (pero definitivamente no se limitan a):

  • Los resultados de las instrucciones anteriores no están disponibles.
  • La caché falla.
  • La ramificación del código, que invalidaría las instrucciones ya obtenidas (lea sobre la predicción de ramificación aquí y aquí ).

Los compiladores modernos intentan ayudar con muchos de los elementos anteriores, luego el procesador se hace cargo. Para un buen ejemplo, vea esta pregunta en otra parte de Stackexchange, que destaca una diferencia importante entre dos instrucciones que pueden hacer lo mismo (en algunas circunstancias). Sin embargo, uno puede ser "más rápido" que el otro en algunos procesadores debido a la unidad de ejecución en uso.

Para una explicación legible por humanos de la tubería moderna de la CPU, vea Un viaje a través de la tubería de la CPU . Para una explicación algo más técnica, ver el artículo de Microarquitectura de Agner Fog .

David
fuente
Gracias por la explicación y los enlaces muy interesantes. Como nota, Cell parece muy interesante, espero estudiar más sobre arquitecturas de CPU ^ _ ^. "" El x86 usa una "superpipelina" como se describió anteriormente. La familia Cell utiliza un enfoque "sinérgico" que involucra nueve mini-cpus. Es cierto que cada mini-CPU sigue una tubería en su mayoría en orden, las mini-cpus tienen múltiples tuberías superescalares paralelas en lugar de una sola tubería. "" "
trabajo el
3

¿Qué crees que sucedió? Todos los ingenieros de Intel, AMD e IBM leyeron que una tubería solo puede entregar un resultado por ciclo, y dijeron "oh, bueno, eso es todo, no pueden hacer que estos procesadores sean más rápidos". ¿O leyeron esto y dijeron: "¿No pueden entregar más de un resultado por ciclo? ¡Ya veremos eso!".

Para una buena introducción a la arquitectura Haswell, por ejemplo, puede seguir este enlace http://www.realworldtech.com/haswell-cpu/ o simplemente puede ir al sitio web de Intel y encontrará un poco de documentación allí.

Cada núcleo del procesador Haswell tiene una gran cantidad de unidades de ejecución, que pueden realizar operaciones independientes entre sí, por lo que se pueden realizar múltiples operaciones en paralelo. A continuación, el procesador Haswell tiene varias unidades de ejecución que manejan operaciones vectoriales de hasta 256 bits de tamaño. Una operación de vector podría, por ejemplo, realizar cuatro operaciones de punto flotante de precisión doble u ocho operaciones de punto flotante de precisión simple en una operación de vector. Y, por último, el procesador Haswell admite "suma múltiple con fusibles", lo que significa que calcular los tiempos b más c es solo una operación.

El máximo teórico, dado que Haswell tiene dos unidades capaces de agregar múltiples con fusibles, es dos operaciones de agregar múltiples con fusibles por ciclo, cada operación realiza ocho multiplicaciones de precisión simple más adiciones, o 32 operaciones de punto flotante de precisión simple.

El procesador 3630 no está en la última lista de precios de Intel, pero hay modelos como el 3740QM con cuatro núcleos. Entonces, en lugar de 32, puede obtener 128 operaciones de punto flotante por ciclo de reloj. Este es el máximo teórico. Lograr la mitad de eso en la vida real es un desafío, pero no imposible para las tareas adecuadas. Hay otros procesadores disponibles con hasta 15 núcleos (para precios que ni siquiera los fanáticos de los juegos más fanáticos pagarán).

Entonces tienes una combinación de varios multiplicadores:

  1. Múltiples núcleos por procesador.
  2. (Hyperthreading, no mencionado anteriormente, le permite acercarse a los límites teóricos)
  3. La operación de multiplicación-suma fusionada realiza dos operaciones aritméticas contando solo como una.
  4. Vectores de 256 bits que realizan 8 operaciones contando solo como uno.
  5. Dos unidades de ejecución de vectores capaces de manejar la suma multiplicada fusionada.

8.6 operaciones por ciclo no es demasiado difícil de lograr. Incluso 8.6 operaciones por ciclo por núcleo no es demasiado difícil.

gnasher729
fuente
Me pregunto si sería práctico o ventajoso diseñar una CPU con algunos núcleos que ejecutaran x86 y algunos que ejecutaran un conjunto de instrucciones optimizado para el comportamiento superescalar. Sé que Intel y AMD hacen algunas cosas increíbles para evitar las limitaciones en el conjunto de instrucciones x86, pero en algunos casos creo que sería útil conocer algunas cosas que el conjunto de instrucciones actual no puede expresar. Por ejemplo, las distintas versiones de las ADDinstrucciones se basan en si el desbordamiento no se debe ver afectado o si se debe configurar cuando se produce el desbordamiento (y se debe configurar si no lo hace).
supercat
1
Me entristece que hoy en día, muchos idiomas predeterminen el no desbordamiento. Sé que Java está bastante atascado por los requisitos semánticos, pero en lenguajes como C # que incluyen operadores aritméticos de captura y no captura, la única buena razón por la que veo que no atrapa el desbordamiento es porque uno necesita un comportamiento de ajuste. En la actualidad, la verificación de desbordamiento puede imponer una penalización de velocidad significativa, pero si un lenguaje de máquina se diseñó en torno a la idea de que la captura de desbordamiento no necesita ser precisa siempre que el código pueda garantizar que no se hayan producido desbordamientos antes de la operación ...
supercat
... alcanza ciertos puntos críticos, debería ser posible reducir la sobrecarga de captura de desbordamiento a casi cero. Si el código realiza un cálculo y luego almacena un valor en una ubicación que se abandonará si se desborda el primer cálculo, no debería ser necesario retrasar el almacenamiento hasta que el procesador sepa si el primer cálculo tiene éxito, pero el procesador actualmente no tiene forma de saber eso. Si el código simplemente pudiera hacer todas las operaciones que se pueden realizar de manera segura, se haya producido o no un desbordamiento, y luego verifique si se produjo un desbordamiento incorrecto en alguna de ellas ...
supercat
... parece que debería ayudar a reducir las dependencias de ejecución.
supercat
2

El punto de referencia Drystone es de 1984, y la máquina VAX 1 MIPS nominal correspondiente no es muy eficiente en términos modernos. Incluso un Cortex M3 ofrece 1,25 DMPIS / MHz.

Los procesadores de arquitectura Intel Core pueden ejecutar múltiples instrucciones en paralelo en un solo núcleo, porque hay múltiples unidades informáticas presentes.

Turbo J
fuente
1

Aprendí mucho de los excelentes y extensos artículos de Jon "Hannibal" Stokes de Ars Technica sobre el tema de la arquitectura de microprocesadores. Los artículos están un poco anticuados (parecen ser de aproximadamente 2004), pero siguen siendo muy relevantes.

Algunos de los enlaces a la siguiente parte de un artículo están rotos, sin embargo, parece que puede solucionarlos usted mismo al comparar cuidadosamente la URL de la primera parte y la URL rota de la página siguiente (por ejemplo, agregando m-algo en la URL).

(sí, esta es una respuesta glorificada de solo enlace, lo siento; los artículos son demasiado buenos para no mencionarlos)

marcelm
fuente