¿Cuántos ciclos de reloj tarda en ejecutarse una instrucción RISC/CISC?

Según Digital Design and Computer Architecture de Harris and Harris, existen varias formas de implementar un procesador MIPS, incluidas las siguientes:

La microarquitectura de ciclo único ejecuta una instrucción completa en un ciclo. (...)

La microarquitectura multiciclo ejecuta instrucciones en una serie de ciclos más cortos. (...)

La microarquitectura canalizada aplica la canalización a la microarquitectura de ciclo único.

Las arquitecturas a menudo se clasifican como RISC o CISC. De RISC contra CISC :

Los procesadores RISC solo usan instrucciones simples que se pueden ejecutar dentro de un ciclo de reloj.

Dado que MIPS es arquitectura RISC, estoy un poco confundido por las definiciones anteriores y me pregunto si no hay algún tipo de contradicción entre ellas. Más específicamente:

  1. Si una instrucción RISC se puede dividir en ciclos más cortos (Fetch, Decode, ...), ¿cómo podemos decir que solo se necesita un ciclo de reloj para ejecutar toda la instrucción? ¿No se necesita un ciclo de reloj para ejecutar cada uno de los pasos?
  2. ¿ Realmente se necesita un ciclo de reloj para ejecutar una instrucción RISC? ¿Qué sucede, por ejemplo, si se produce una pérdida de memoria caché y el procesador tiene que esperar a que la DRAM sea lenta? ¿No debería esto prolongar un poco la ejecución de la instrucción?
  3. ¿Qué es exactamente un ciclo de instrucción? ¿Es el tiempo que tarda una instrucción en terminar (es decir, uno o varios ciclos de reloj)?
  4. ¿Cuánto tarda una instrucción CISC en ciclos de reloj/instrucción?
Por lo general, no menos de uno :-).

Respuestas (4)

Las definiciones prácticas de RISC y CISC están tan confusas y borrosas que ahora casi no tienen sentido. Ahora es mejor pensar en ellos como más sobre "filosofía", en el sentido de que una arquitectura CISC tiene un conjunto de instrucciones más rico con instrucciones individuales más potentes (por ejemplo, DIV y similares), mientras que un conjunto de instrucciones RISC es simple y rápido. y deja que el compilador implemente operaciones complejas. Incluso los conjuntos de instrucciones supuestamente CISC (como x86) se traducen en instrucciones internas en chips Intel y AMD y se implementan más como procesadores RISC. Para responder tu pregunta:

  1. Los procesadores RISC académicos originales (y creo que tal vez las primeras versiones comerciales) ejecutaron una instrucción por ciclo, incluidas la búsqueda y la decodificación. Esto fue posible porque los caminos de datos estaban súper limpios porque las operaciones de cada etapa eran simples y bien definidas. (La compensación aquí es que solo se pueden implementar instrucciones muy simples de esta manera). Una vez que llegó al mundo real, las cosas se volvieron borrosas. Cosas como la canalización y la arquitectura superescalar hacen imposible una simple dicotomía RISC/CISC.

  2. Los chips RISC originales intentaron ejecutar una instrucción por ciclo y podían hacerlo si los datos estaban disponibles en el archivo de registro. Por supuesto, si el procesador tuviera que ir a DRAM, tomaría (mucho) más tiempo. RISC se trata de "intentar" ejecutar una instrucción por ciclo.

  3. Un ciclo de instrucción es el tiempo que transcurre entre búsquedas.

  4. Depende enormemente de la instrucción y de la arquitectura del conjunto de instrucciones. Incluso en una arquitectura CISC, algunas instrucciones podrían ejecutarse muy rápidamente (como un desplazamiento hacia la izquierda o hacia la derecha, por ejemplo). Algunos se ejecutaron muy lentamente (10s de ciclos o más). La arquitectura VAX (probablemente el pináculo de la filosofía CISC) tenía instrucciones que eran realmente complejas. Por cierto, una arquitectura CISC suele ser más fácil de programar en ensamblador que una arquitectura RISC porque es casi como un lenguaje de alto nivel.

> en el sentido de que una arquitectura CISC tiene un conjunto de instrucciones más rico. No, muchos risc tienen instrucciones más ricas que cisc

la respuesta corta

  1. Los pasos para decodificar y ejecutar la instrucción se ejecutan en paralelo con el siguiente paso de la instrucción anterior. Esta técnica se conoce como canalización. Consulte Acerca de los procesadores RISC a continuación.

  2. Una arquitectura RISC de un solo problema generalmente promediará un poco menos de una instrucción por ciclo debido a los estados de espera y el tiempo necesario para las operaciones de carga/almacenamiento que llegan a la memoria en lugar de solo registrarse. Las ranuras de retardo le brindan un gancho arquitectónico que puede permitirle recuperar parte de este tiempo. Consulte Acerca de los procesadores RISC a continuación.

  3. Un ciclo de instrucción es el tiempo necesario para ejecutar una instrucción. Esto variará con la arquitectura y (en algunos casos) las instrucciones. Por ejemplo, la mayoría de las instrucciones en algo como MIPS R2000/3000 toman un ciclo. Las instrucciones que involucran el acceso a la memoria (cargar/almacenar, bifurcar) toman más de un ciclo, aunque las ranuras de retardo significan que puede ejecutar algo más (posiblemente solo un NOP) en la ranura de retardo. Las arquitecturas no canalizadas pueden tener ciclos de instrucción de varios ciclos de reloj, que a menudo varían según el modo de direccionamiento. Consulte Acerca de los procesadores RISC, las arquitecturas CISC tradicionales y las arquitecturas cableadas a continuación.

    Los diseños de problemas múltiples pueden desdibujar un poco este concepto al ejecutar más de una instrucción en paralelo.

  4. Los procesadores CISC pueden tener instrucciones que toman diferentes períodos de tiempo. El número exacto de ciclos de reloj depende de la arquitectura y las instrucciones. El número variable de ciclos de reloj tomados en CISC ISA es una de las razones por las que son difíciles de integrar en arquitecturas con muchas canalizaciones. Consulte las arquitecturas CISC tradicionales a continuación.

La respuesta más larga

Para un solo problema MIPS, SPARC u otra CPU, todas (para una primera aproximación) las instrucciones se emiten en un ciclo, aunque pueden tener algo conocido como "ranura de retraso".

En procesadores RISC

En este contexto, una CPU de un solo problema es aquella en la que la CPU no realiza ningún análisis de dependencia sobre la marcha ni emite instrucciones en paralelo como lo hacen las CPU modernas, es decir, tienen una sola unidad de ejecución que ejecuta las instrucciones en el orden en que se leen de memoria. Más sobre esto más adelante.

La mayoría de los procesadores RISC más antiguos son diseños de un solo problema, y ​​estos tipos todavía se usan ampliamente en sistemas integrados. Un núcleo RISC entero de un solo problema de 32 bits se puede implementar en alrededor de 25 000-30 000 puertas, por lo que los núcleos de CPU de este tipo tienen un consumo de energía muy bajo y un tamaño muy pequeño. Esto hace que su integración en productos SOC (system-on-chip) sea fácil y económica.

Los diseños de CPU RISC están canalizados: el procesamiento de la instrucción se realiza en varias etapas, y cada instrucción se pasa por la canalización a la siguiente etapa en cada ciclo de reloj. En la mayoría de los casos, una CPU canalizada de un solo problema ejecutará algo cercano a una instrucción por ciclo de reloj.

Algunas arquitecturas tienen instrucciones como bifurcación o carga/almacenamiento desde la memoria donde el ciclo adicional tomado por el acceso a la memoria es visible para el código.

Por ejemplo, en un diseño SPARC V7/V8 , la siguiente instrucción después de una bifurcación se ejecuta realmente antes de que tenga lugar la propia bifurcación. Por lo general, colocaría un NOP en la ranura después de la bifurcación, pero podría colocar otra instrucción si pudiera encontrar algo útil que hacer.

La arquitectura MIPS R2000/R3000 tenía una ranura de retraso similar en las instrucciones de carga/almacenamiento. Si cargó un valor de la memoria, en realidad no aparecería en el registro para otro ciclo. Podría poner un NOP en la ranura o hacer otra cosa si pudiera encontrar algo útil que hacer que no dependiera de la operación de carga que acaba de ejecutar.

Si la memoria era más lenta que la CPU, lo que sucedía con frecuencia, podría obtener estados de espera adicionales en los accesos a la memoria. Los estados de espera congelan la CPU durante uno o más ciclos de reloj hasta que se completa el acceso a la memoria. En la práctica, estos estados de espera y el tiempo adicional para los accesos a la memoria significan que los diseños de CPU de un solo problema promedian un poco menos de una instrucción por ciclo de reloj. Las ranuras de retardo le brindan algunas oportunidades posibles para optimizar el código ejecutando alguna otra instrucción mientras se lleva a cabo una operación de memoria.

Procesadores CISC tradicionales

Los procesadores CISC eran diseños que podían tener instrucciones que tomaban diferentes períodos de tiempo. A menudo tenían instrucciones más complejas implementadas directamente en hardware que tendrían que hacerse en software en una CPU RISC.

La mayoría de las arquitecturas de mainframe y casi todos los diseños de PC hasta el M68K y el Intel 386 eran CPU CISC microcodificadas tradicionales. Estos diseños demostraron ser más lentos por reloj y usaron más puertas que las CPU RISC.

microcódigo

Un ejemplo de una arquitectura microcodificada (MOS 6502) se puede ver en la emulación aquí . El microcódigo se puede ver en la parte superior de la imagen.

El microcódigo controla los flujos de datos y las acciones activadas dentro de la CPU para ejecutar instrucciones. Al recorrer los pasos en el microcódigo, puede activar las partes de una CPU, mover datos a través de ALU o llevar a cabo otros pasos. Los componentes reutilizables de la CPU se pueden coordinar en varios ciclos de reloj para ejecutar una instrucción. En el caso del 6502, el microcódigo también podría ejecutar algunas acciones segmentadas.

Los diseños microcodificados usaban menos silicio que los chips cableados a expensas de tomar potencialmente varios ciclos de reloj para completar una instrucción. Según el diseño, estas CPU tardarían diferentes períodos de tiempo por instrucción.

Arquitecturas cableadas

Los diseños cableados (que no necesariamente se excluyen mutuamente con el microcódigo) ejecutan una instrucción de forma síncrona o pueden tener sus propios coordinadores para hacer algo en múltiples ciclos de reloj. Por lo general, son más rápidos a expensas de un hardware más dedicado y, por lo tanto, son más costosos de implementar que un diseño microcodificado de funcionalidad equivalente.

Un ejemplo famoso de esto fue la CPU Amdahl 470/6 original , que fue un reemplazo directo de la CPU en ciertos modelos IBM System/370. La CPU Amdahl era un diseño cableado en un momento en que las CPU 370 de IBM se basaban en gran medida en el microcódigo. La CPU de Amdahl era aproximadamente 3 veces más rápida que las CPU de IBM que reemplazaron.

No hace falta decir que a IBM no le hizo gracia y esto resultó en una batalla judicial que terminó obligando a IBM a abrir su arquitectura de mainframe hasta que expiró el decreto de consentimiento hace unos años.

Por lo general, un diseño cableado de este tipo todavía no era tan rápido reloj por reloj como una CPU RISC, ya que los diferentes tiempos y formatos de instrucción no permitían tanto margen para canalizar como lo hace un diseño RISC.

Diseños de múltiples números

La mayoría de las CPU modernas son arquitecturas de múltiples problemas que pueden procesar más de una instrucción a la vez dentro de un solo hilo. El chip puede hacer un análisis de dependencia dinámico en el flujo de instrucciones entrantes y emitir instrucciones en paralelo donde no hay dependencia del resultado de un cálculo anterior.

El rendimiento de estos chips depende de cuánto paralelismo se pueda lograr en el código, pero la mayoría de las CPU modernas promediarán varias instrucciones por ciclo en la mayoría de los códigos.

Intel moderno y otras CPU x86/X64 ISA tienen una capa que interpreta el conjunto de instrucciones CISC de la vieja escuela en microinstrucciones que se pueden alimentar a través de un núcleo de problemas múltiples de estilo RISC canalizado. Esto agrega una sobrecarga que no está presente en las CPU con ISA que están diseñadas para canalización (es decir, arquitecturas RISC como ARM o PowerPC).

diseños VLIW

Los diseños VLIW, de los cuales Intel Itanium es quizás el más conocido, nunca despegaron como arquitecturas convencionales, pero IIRC hay varias arquitecturas DSP que utilizan este tipo de diseño. Un diseño VLIW hace que los problemas múltiples sean explícitos con una palabra de instrucción que contiene más de una instrucción que se emite en paralelo.

Estos dependían de buenos compiladores de optimización, que identificaban dependencias y oportunidades para el paralelismo, colocando instrucciones en las múltiples ranuras disponibles en cada palabra de instrucción.

Las arquitecturas VLIW funcionan bastante bien para aplicaciones numéricas, ya que las operaciones de matriz/arreglo tienden a ofrecer oportunidades para un paralelismo extenso. El Itanium tuvo un nicho de mercado en aplicaciones de supercomputación durante un tiempo, y hubo al menos una arquitectura de supercomputadora, Multiflow TRACE , que se produjo utilizando un ISA de este tipo.

Memoria y almacenamiento en caché

Las CPU modernas son mucho, mucho más rápidas que la memoria, por lo que las lecturas directas de la memoria pueden generar cientos de estados de espera que bloquean la CPU hasta que se completa el acceso a la memoria. El almacenamiento en caché, que ahora se realiza en varias capas, contiene las ubicaciones de memoria utilizadas más recientemente en la memoria caché. Dado que las CPU suelen pasar la mayor parte del tiempo ejecutando código en bucles, esto significa que obtiene buenos índices de aciertos de reutilización de ubicaciones de memoria que ha utilizado recientemente. Esta propiedad se llama 'localidad de referencia'.

Donde obtiene la localidad de referencia, la CPU puede operar a una velocidad cercana a la óptima. Los errores de caché al siguiente nivel provocan una serie de estados de espera; las fallas de caché en la memoria principal pueden generar cientos.

Por lo tanto, el rendimiento real de los chips de la CPU puede depender en gran medida de la eficiencia de los patrones de acceso a la memoria. Se han escrito libros completos sobre cómo optimizar el código para esto, y es un tema complejo por derecho propio.

Es una simplificación para los estudiantes.

Cada procesador no trivial está canalizado. Hay una unidad de captación previa que entrega las instrucciones en un extremo, varias unidades de ejecución en el medio que realizan el trabajo real y una unidad de emisión responsable de declarar las instrucciones completadas después de que finaliza la escritura en el registro o la memoria. Si hay varias unidades de ejecución (por ejemplo, una ALU entera, una ALU de punto flotante y una unidad vectorial), puede ser posible emitir (a veces llamado "retirar") varias instrucciones por ciclo de reloj. ¿Cómo puede una CPU entregar más de una instrucción por ciclo? entra en muchos más detalles sobre esto.

Como dices, ¿qué pasa si hay un retraso de pérdida de caché? Intel Hyperthreading es una solución novedosa para esto: dos lotes de registros de estado de CPU, un lote de lógica de control y unidades de emisión. Tan pronto como una CPU virtual se detenga, cambie al estado de la otra. (esto es una gran simplificación en sí mismo)

El resultado de esto es que los manuales de CPU modernos brindan tiempos de instrucción mucho más vagos, y es mucho más difícil escribir un código de tiempo con precisión de ciclo, si por ejemplo, está tratando de generar video en tiempo real desde un hardware que no debería ser capaz de hacerlo .

(La respuesta específica a "¿Cuánto tiempo tarda una instrucción CISC en ciclos de reloj/instrucción?" es "busque en el manual de referencia del fabricante y tendrá tiempos por instrucción")

Los otros muchachos han escrito mucho material bueno, así que seré breve en mi respuesta: en los viejos tiempos (1980 aquí), se consideraban los procesadores de 8 bits del día (6800, 6502, Z80, 6809 y otros). CISC. Algunas instrucciones podrían ejecutarse en 2 ciclos de reloj, pero estas eran instrucciones simples, como configurar/borrar bits de bandera en un registro de estado del procesador. Otras instrucciones pueden tomar de 2 a 6 e incluso hasta 9 ciclos de reloj para ejecutarse. Estos procesadores tenían algunas instrucciones bastante poderosas, el Z80 tenía algunas instrucciones de limpieza de bloques de memoria que escribirían el mismo valor en una serie de bytes en la memoria, borrando efectivamente un bloque grande en una sola instrucción, solo configure algunos registros y ejecute el Instrucción LDIR (cargar, incrementar y repetir).

El procesador 6502 (de la memoria) tenía 56 instrucciones pero 13 modos de direccionamiento creando un poderoso conjunto de instrucciones.

RISC vino mucho y adoptó un enfoque diferente, tiene un puñado de instrucciones que se ejecutan en un solo ciclo de reloj. Los programas tienden a ser más largos y ocupan más memoria porque las instrucciones son simples en cuanto a las operaciones que realizan, por lo que necesita más de ellos.

Si no recuerdo mal, el primer intento de una arquitectura RISC fue el transputer o el procesador Acorn Risc.

Podría decirse que la primera arquitectura de tipo RISC canalizada fue la CDC 6600 diseñada por Seymour Cray. Eso fue un par de décadas antes de que el término RISC se generalizara. MIPS, ARM y algunos otros diseños de microprocesadores RISC se remontan al período 1980-1985 con el primer hardware comercial que utiliza estos chips a mediados de la década de 1980.
Los chips transputer individuales eran bastante rápidos, pero no tenían el mismo tipo de arquitectura que uno normalmente asocia con un chip RISC. en.wikipedia.org/wiki/Transputer#Architecture
Tengo un par de transputadoras en una caja antiestática, solo parte de una colección histórica de microprocesadores. Nunca los usé, habría sido muy divertido en esos días experimentar con ellos.
@ConcernedOfTunbridgeWells Acabo de echar un vistazo al conjunto de instrucciones CDC 6600. Si bien el diseño parece encarnar (y anticipar) algunos de los principios de RISC, la instrucción de división de coma flotante tarda 29 ciclos en ejecutarse. Y la misma inclusión de una instrucción de división va en contra de los principios típicos de RISC, ¡pero gracias por el interesante comentario!
Los principales atributos RISC-ish eran el mecanismo de obtención/descodificación/ejecución de instrucciones canalizadas y la arquitectura de almacenamiento de carga (es decir, sin modos de direccionamiento con accesos implícitos a la memoria para calcular la dirección). De hecho, algunos conjuntos de instrucciones RISC (p. ej., IBM POWER) son bastante grandes, pero aún utilizan el enfoque de carga/almacenamiento para garantizar tiempos de ejecución constantes.
En realidad, no se canalizó hasta el CDC 7600.