La microarquitectura CPU es una gran desconocida, pero que se debería tener muy en cuenta a la hora de elegir el próximo microprocesador que vas a adquirir. De ella depende el rendimiento y otras prestaciones del chip que vas a comprar.
A veces se camufla con algunos parámetros que pueden ser más cuestión de marketing que otra cosa, como el tamaño de la memoria caché, la frecuencia de reloj o las numerosas marcas patentadas para designar a una tecnología que tal vez tiene la competencia, pero no se ha molestado en patentar una marca para designarla.
Índice de contenidos
ISA vs microarquitectura: diferencias
Es importante no confundir una microarquitectura de CPU y una arquitectura o ISA (Instruction Set Architecture), ni tampoco con el sistema en sí o macroarquitectura. Aunque puedan parecer términos similares, lo cierto es que existen diferencias entre ellos:
- Macroarquitectura o diseño del sistema: representa todo el diseño del sistema completo que compone al computador en cuestión, es decir, no solo la CPU, sino el resto de hardware básico, como el bus, el controlador de memoria, la memoria principal, unidades de procesamiento extras que operen junto con la CPU, controladores, sistema DMA, E/S (Entrada y Salida para periféricos), etc. Es decir, la mayoría de elementos que se encuentran en la placa base.
- ISA: se refiere a las instrucciones que la CPU puede comprender y ejecutar, además de definir también el tamaño de palabra, cantidad de registros disponibles, modos de direccionamiento de memoria, y el formato de los datos que se pueden manejar. Esto está íntimamente relacionado con el ASM o lenguaje ensamblador, ya que los mnemónicos empleados para las instrucciones son los usados también para este lenguaje de más bajo nivel (p.e.: ADD, SUB, MUL, ).
- Microarquitectura u organización de la computadora: no es más que una implementación de una ISA. Es decir, la representación de los data paths, las unidades de ejecución, los bancos de registros, buses, etc. Esta microarquitectura se pasa a un diseño lógico y luego a uno físico/electrónico, es decir, el circuito integrado de la CPU.
También existe lo que se conoce como UISA o μISA, es decir, una Microcode Instruction Set Architecture, aunque esto es algo en lo que no entraremos.
¿Qué es una microarquitectura CPU?
La microarquitectura CPU, µarch, es una implementación de la propia ISA. De ella dependerá el cómo se ejecutan las instrucciones y qué instrucciones o tipos de datos se aceptan. Esta implementación abarca las diferentes partes de la CPU y las tecnologías o paradigmas que pueda usar. Por ejemplo:
- Tipo de unidad de control y microcódigo: algunos microprocesadores antiguos o más sencillos usaban una unidad cableada más rápida y eficiente, sin embargo, la mayoría de los actuales microprocesadores usan unidades más complejas y programables. De esta unidad dependerá la cantidad de instrucciones que podrá interpretar la CPU, es decir, si solo acepta algunas o la ISA completa (con o sin extensiones). Como sabrás, este microcódigo se puede actualizar.
- Tamaño, tipo y jerarquía de la memoria caché: es otra de las cuestiones técnicas que se alteran dentro de una microarquitectura, y es importante para acelerar los accesos de memoria y tratar de minimizar el impacto por la latencia con la memoria principal o el sistema E/S. Por ejemplo, en el diseño se tiene en cuenta:
- Cuál será el LLC o el último nivel de la memoria caché y, por tanto, la cantidad de niveles que tendrá.
- TLB y forma de actuar en caso de fallo de caché.
- Niveles de caché especiales, como la de traza.
- Tipos de memoria empleada.
- Capacidad.
- Dividida (I/D) o unificada.
- Frecuencia de reloj a la que funcionará (igual al núcleo de la CPU o diferente)
- etc.
- Pipeline: la mayoría de CPUs modernas están canalizadas, es decir, se han dividido en varias etapas en las cuales cada salida es la entrada de la etapa posterior. De este modo se puede dividir el proceso y hacer que aumente la cantidad de instrucciones en paralelo. Todo dependerá de la profundidad o niveles de la pipeline. Por ejemplo:
- CPU sin pipeline: entra una instrucción y no podrá entrar la siguiente hasta que termine por completo la anterior.
- CPU con 4 etapas: si esas etapas son fetch, deco, exe, escritura, la primera instrucción entraría en el ciclo fetch o de búsqueda. Cuando termine dicha etapa pasaría a la decodificación para que pueda ser interpretada, y después a la unidad de ejecución correspondiente para obtener el resultado, y por último se escribe en memoria. Cuando la primera instrucción ha pasado a deco, ya puede entrar otra nueva en fetch y así sucesivamente. Eso significará que pasados unos ciclos de reloj, la CPU habrá llenado su cauce o etapas y estaría procesando varias instrucciones a la vez.
- Cantidad y tipo de unidades de ejecución: se puede elegir la cantidad de unidades funcionales que ejecutarán las instrucciones, como ALUs, FPUs, AGUs, MULs, MACs, etc., algunas de ellas dirigidas a datos enteros y otras a datos en coma flotante. Esto es lo que diferencia a un procesador escalar de uno superescalar (con varias unidades de un mismo tipo para acelerar la ejecución).
- Ejecución especulativa: muchos microprocesadores modernos también hacen uso de una técnica que permite ejecutar instrucciones previas a un salto o branch antes de conocer el resultado de dicha bifurcación del código. De esa forma, si aciertan, ya tendrán el resultado obtenido. De lo contrario, deberían vaciar el cauce y procesar el correcto. Para tener el mayor números de aciertos posibles y minimizar la penalización por fallo, se emplean unidades de predicción que pueden ser de muy diversos tipos, e incluso usar redes neuronales.
- Orden de ejecución: algunas CPUs tienen ejecución en orden y son más simples, pero con un rendimiento inferior. La mayoría de CPUs de alto rendimiento usan el paradigma de OoOE (Out of Order Execution) o ejecución fuera de orden. Esto implica que se pueden ir procesando las instrucciones que tengan sus datos ya listos para ser procesados, aunque no estén en el mismo orden secuencial del programa. Luego se reordenan y se obtiene el resultado igual que en uno en orden. Lo que se consigue así es evitar tiempos idle u ociosos cuando los datos de una instrucción no están preparados y hay que esperar.
- Renombre de registros: es otra técnica muy empleada en los microprocesadores de alto rendimiento en el que hay una abstracción de los registros lógicos y los físicos. Cada registro lógico tiene asociado un conjunto de registros físicos. Cuando en el código del binario que se ejecuta se hace referencia a un registro lógico, la CPU lo transpone a uno físico sobre la marca. Los registros físicos son opacos para el programador, pero gracias a esta técnica se pueden eliminar algunas dependencias de datos que surgen.
- Multiprocesamiento y multihilo: por supuesto, cuando se diseña la microarquitectura se piensa en aumentar el procesamiento paralelo con otros métodos adicionales:
- Se puede pensar en un singlecore o en un multicore (e incluso manycore), variando los números de núcleos que trabajan simultáneamente, de uno a varios, decenas o miles de ellos.
- O en un sistema MP, para montar varios microprocesadores en una misma placa base y que ayuden entre sí comunicándose por mallas como HT, Infinity Fabric, Intel Mesh, etc.
- E incluso paralelismo a nivel de hilo, con implementaciones como SMT (Simultaneous MultiThreading). Mientras cada núcleo puede trabajar con un proceso, cuando se implementa SMT, cada núcleo pasa a poder manejar hasta dos hebras o threads simultáneamente, cambiando de un contexto a otro para acelerar la ejecución. Es decir, es como si un núcleo físico se divide en varios núcleos lógicos.
Todo esto es lo que realmente hace a una CPU rendir más o menos, y ser mejor en ciertos ámbitos u otros. Otras características técnicas como la frecuencia de reloj, etc., son menos relevantes.
Compatibilidad en las microarquitecturas e implementación
Como he comentado, la microarquitectura de CPU es una implementación de una ISA, por lo que podría haber varias implementaciones diferentes para una misma ISA. Es más, para la ISA AMD64 o EM64T o x86-64, como la quieras llamar, existen muchas implementaciones o microarquitecturas diferentes tanto de la compañía AMD como de la compañía Intel, e incluso otros como Zhaoxin (VIA Technologies), Hygon Dhyana (Zen1 con licencia AMD), etc. Y no solo eso, dentro de una misma compañía puede haber generaciones y generaciones de microarquitecturas que van desarrollándose para obtener mejores prestaciones.
Por ejemplo, si observamos a AMD y la ISA AMD64, nos encontramos con microarquitecturas como:
- K8/Hammer (Turion64, Sempron, Athlon64, Opteron)
- K10 (Phenom, Athlon, Sempron, A-Series,…)
- Bulldozer (Opteron, FX-Series,…)
- Zen (Ryzen, Threadripper, EPYC…)
- Zen+
- Zen 2
- Zen 3…
Por supuesto, también existen otras microarquitecturas no compatibles con esta ISA, sino que pertenecen a otras ISAs diferentes. Por ejemplo, un chip basado en la ISA ARM (A64), como uno con microarquitectura Avalanche+Blizzard (Apple A15 Bionic), no podría ejecutar los binarios compilados para una x86 o cualquier otra ISA que no sea la suya. Por este motivo, ejecutar un software para otra ISA en un equipo cuya ISA no es la misma es imposible, a no ser que sea mediante el uso de emuladores como QEMU, Rosetta 2, etc.
Ni siquiera un microprocesador con una microarquitectura perteneciente a una misma ISA te garantiza que sea compatible con todo el repertorio de instrucciones completo (puede estar diseñado para ejecutar solo un subset), o con las extensiones que pueda tener. Por ejemplo, no todos los chips son compatibles con la extensión de instrucciones AVX512. Esto nos lleva a pensar que ni siquiera un software compilado para una misma arquitectura puede funcionar igual en todas las CPUs. Por ejemplo, un binario compilado para funcionar en una Raspberry Pi (ARM), no podría ser ejecutado en un Apple M1 (ARM), ni viceversa.
Cuando se compila un software, generalmente se hace de la forma más genérica posible, sin optimizaciones para una microarquitectura específica. Eso garantiza que funcione en el mayor número de procesadores posibles. Por ejemplo, aunque un chip de AMD no tenga ciertas instrucciones o extensiones, puede ejecutar perfectamente el software al igual que un Intel, solo que es muy probable que tenga que ejecutar más instrucciones. Sin embargo, si se compila de forma optimizada para una microarquitectura concreta, mejorará mucho el rendimiento, al usar todas las instrucciones posibles.
Licencias
Del apartado anterior también puede surgir la duda de si esas implementaciones son libres o están bajo algún tipo de control. Es importante destacar que una ISA está registrada y protegida por una licencia, al igual que lo está el software. Por tanto, cualquiera no puede crear una implementación (microarquitectura CPU) para una ISA sin más, ya que supondría infringir la ley. No obstante, existen algunas ISAs bajo licencias abiertas, que permiten ser usadas sin dichas restricciones.
Veamos algunos ejemplos prácticos:
- Licencias cerradas: están protegidas por una licencia propietaria y otros no pueden realizar implementaciones legales.
- IA-32 (x86-32): fue creada por Intel, y otros lograron licencias como AMD, Winchip, Nextgen, IDT, VIA, etc. Sin embargo, hubo un gran número de juicios por litigios en la época.
- AMD64 (x86-64): esta vez fue AMD el que tomó la delantera y diseñó esta nueva ISA, una extensión de 64-bit de la anterior. Intel la denomina EM64T, y no hay que confundirla con IA-64 de Intel, que es una arquitectura de 64-bit destinada a HPC con sus microprocesadores Itanium. Intel puede usarla por un acuerdo de licencias cruzadas obtenido entre ambas compañías. Además, otros como Hygon Dhyana también han conseguido licencias de AMD (solo para Zen 1) para el mercado chino.
- Licencias flexibles: las licencias que denomino flexibles son aquellas que permiten licenciar tanto la propia ISA como licenciar núcleos IP a sus clientes. Lo hacen bajo varios métodos de pago o suscripción, similares a otros servicios.
- SPARC: fue creada inicialmente por Sun Microsystems, empresa que ya no existe, y que fue absorbida hace años por Oracle. Ahora ésta es la que tiene los derechos de la ISA, y tiene un sistema similar al de ARM, permitiendo a otros que puedan crear sus propias implementaciones.
- OpenPOWER: similar a la anterior. IBM sigue creando sus POWER para HPC, pero permite que otros puedan obtener sus propias implementaciones.
- ARM: es uno de los casos más más relevantes en la actualidad, permitiendo varios tipos de licenciamiento que pueden ir desde los 0€ hasta los varios millones de euros. Por ejemplo, permite usar la ISA para el ámbito académico o investigación, vender IP cores de sus núcleos Cortex A, Cortex M, Cortex R o los Neoverse, así como una licencia llamada BoC para permitir a terceros obtener los núcleos IP y realizar modificaciones en su microarquitectura, e incluso licenciar solo la ISA. Ejemplos prácticos:
- Los núcleos Kryo para los Snapdragon de Qualcomm usan una tipo BoC.
- Apple Silicion simplemente paga por la licencia de la ISA y crea ella misma las microarquitecturas.
- Otros comprar núcleos IP Neoverse como es el caso del procesador europeo del proyecto EPI.
- Licencias abiertas: sí que permiten la creación de microarquitecturas, siguiendo un modelo como el del código abierto en el software. Por ejemplo:
- RISC-V: es una ISA abierta bajo licencia BSD (permisiva), lo que permite crear microarquitecturas a partir de ella a cualquiera, sin pagar nada, y dichas microarquitecturas pueden ser también abiertas o cerradas.
- MIPS: muy similar a RISC-V, pero especialmente dirigida al sector IoT.
No solo la ISA está patentada, también está la implementación o microarquitectura CPU, ya que se trata de un diseño de propiedad intelectual. No obstante, en estos casos también existen algunas abiertas y que se distribuyen como soft-core, creadas en lenguajes como Verilog, VHDL, Chisel, etc.
Con esto terminamos nuestra artículo sobre las microarquitectura CPU. ¿Te ha parecido interesante? ¿Te interesa que escribamos sobre algo en particular? ¡Te escuchamos!