Skip to content

English · Español

01 — Del transistor a la CPU

De abajo a arriba: transistor → puerta → ALU → pipeline → ejecución especulativa. Nivel de detalle: suficiente para entender por qué hay caches y por qué mispredict cuesta ciclos, no para diseñar un chip.


Por qué de abajo a arriba

Puedes usar una CPU sin saber lo que hay dentro de ella. Pero cada número de rendimiento con el que te encontrarás — 3 GHz, 4 cores, 8 threads, AVX2, coste de mispredict de salto 12-20 ciclos — es una abstracción con fugas sobre la máquina física. Cuando la fuga importa (importará), necesitas saber qué abstracción se rompió. Así que: de abajo a arriba, rápido.

El ritmo de abajo es deliberadamente agresivo. Cada sección es un párrafo de modelo mental más uno o dos números que vale la pena memorizar. No estamos construyendo un curso de lógica digital; estamos fijando el vocabulario que usan las mediciones de la Fase 1.

Transistor

Un transistor es un switch controlado por voltaje. Aplicas voltaje a un terminal (gate), y la corriente fluye o no entre los otros dos (source / drain). Eso es todo. Todo lo demás en tu CPU son miles de millones de estos organizados en patrones.

Dos números a recordar: - Recuento moderno de transistores en una die de CPU: decenas de miles de millones (el i5-8250U de Intel tiene ~6B; un H100 tiene ~80B). - Retardo de conmutación de un transistor: picosegundos (10⁻¹² s).

El tiempo de conmutación en picosegundos es lo que hace posibles los relojes de GHz. Si la conmutación tardara microsegundos, los ordenadores correrían a kHz.

Puerta lógica

Si cableas transistores en patrones obtienes puertas lógicas: NAND, NOR, AND, OR, XOR, NOT. Solo con NAND es funcionalmente completo — cada otra operación se puede construir a partir de NAND. Los chips reales usan una mezcla porque la optimización de área y potencia premia la diversidad.

Un puñado de NANDs forma un sumador de 1 bit. Un montón de sumadores de 1 bit encadenados forman un sumador de N bits. Un multiplexor + sumador + unas pocas puertas de control forman una ALU (Arithmetic Logic Unit) — la parte de la CPU que realmente computa a + b o a & b.

Reloj

Las puertas lógicas necesitan tiempo para estabilizarse después de que cambien sus entradas. El reloj es una señal de onda cuadrada (alto / bajo / alto / bajo) que regula cuándo se leen los resultados. En cada ciclo de reloj, la ALU toma las entradas, computa, y el resultado se enclava en el siguiente flanco de reloj.

  • Periodo de reloj = 1 / frecuencia. Una CPU a 3 GHz tiene un periodo de reloj de 333 ps.
  • "Ciclos por instrucción" (CPI) es el número de ciclos de reloj que tarda una instrucción dada. Las CPUs modernas pueden tener CPI < 1 (múltiples instrucciones por ciclo) gracias al pipelining.

Pipeline

Una CPU ingenua haría: buscar instrucción, decodificarla, ejecutarla, escribir resultado — una a la vez. El pipelining se da cuenta de que esas cuatro etapas usan partes distintas del chip, así que mientras la etapa 1 está buscando la instrucción N+1, la etapa 2 puede decodificar la instrucción N, la etapa 3 puede ejecutar la instrucción N-1, la etapa 4 puede escribir el resultado de la instrucción N-2. Cuatro instrucciones en vuelo a la vez, una terminando por ciclo.

Las CPUs reales tienen 10–20 etapas de pipeline, no 4. Cuanto más largo el pipeline, más alto puede subir el reloj (cada etapa hace menos trabajo, así que el periodo de reloj puede ser más corto) y más dolorosas se vuelven las stalls del pipeline.

Una stall ocurre cuando la etapa k+1 necesita la salida de la etapa k antes de que la etapa k haya terminado. Ejemplo: la instrucción N+1 necesita el resultado de la instrucción N. El pipeline tiene que esperar — "bubble" — desperdiciando ciclos.

Las grandes causas de stall: - Hazards de datos. N+1 depende del resultado de N. - Hazards de control. Un salto (if, bucle) — hasta que el salto se resuelve, la CPU no sabe qué instrucción buscar a continuación. - Hazards de memoria. N+1 lee de memoria; si el valor no está en cache, el pipeline espera cientos de ciclos a la DRAM.

Predicción de saltos y ejecución especulativa

Los hazards de control son constantes — cada bucle, cada if — así que las CPUs usan un predictor de saltos: una pequeña pieza de hardware que adivina, antes de que el salto se resuelva, hacia dónde irá, y empieza a buscar por el camino predicho. Si la suposición es correcta (>95% del tiempo para código típico), el pipeline nunca se detiene. Si es incorrecta, las instrucciones traídas especulativamente se descartan — penalización por mispredict, ~12-20 ciclos en CPUs modernas.

Por eso el código pesado en if puede ser más lento que el código pesado en aritmética: cada salto impredecible es una bubble de 15 ciclos. Los cuerpos de bucle que hacen sobre todo aritmética con conteos de iteración predecibles corren a tope; los cuerpos de bucle llenos de if (data[i] > threshold) sobre datos aleatorios son 5–10× más lentos porque el predictor falla la mitad de las veces.

Para los propósitos de la Fase 1: el coste de mispredict de salto es despreciable comparado con un cache miss. Lo mencionamos porque es vocabulario que aparece en la salida del profiling. Mantén el foco en la memoria.

Ejecución fuera de orden

Más allá de predecir saltos, las CPUs modernas reordenan las instrucciones al vuelo. Si la instrucción N+1 no depende de N, pero N+2 no depende de ninguna y está lista para ejecutarse, la CPU puede ejecutar N+2 antes que N. El resultado final, tal como lo observa el programa, es el mismo que la ejecución en orden (el estado arquitectónico es el mismo), pero el pipeline se mantiene lleno.

Esto es maravilloso para el rendimiento y terrible para la predictibilidad. El profiling de CPUs fuera de orden es una pequeña industria. La conclusión para la Fase 1: ya no puedes razonar sobre tiempos de instrucciones individuales — solo sobre kernels con suficientes instrucciones para que domine el comportamiento medio.

Cores, threads, hyperthreading

Un core es un pipeline completo — fetch, decode, execute, write-back — más sus propias caches L1 y L2. Una CPU de 4 cores tiene 4 pipelines completos corriendo en paralelo.

Hyperthreading (SMT) permite a un core mantener dos conjuntos de registros arquitectónicos y alternar entre ellos rápidamente. Cuando un hilo se detiene (cache miss), el otro corre. Para el OS esto parece 2 cores. Para el throughput pico da un speedup de ~1.2-1.4×, no 2×, porque las unidades de ejecución subyacentes se comparten.

El i5-8250U de Borja: 4 cores, 8 threads. nproc devuelve 8. Para los benchmarks compute-bound (los labs de la Fase 1), usa 4 threads como límite superior, no 8. El Lab 02 capturará esto.

SIMD: AVX y compañía

Una instrucción ADD normal suma dos escalares. Una instrucción SIMD (Single Instruction Multiple Data) suma vectores de escalares en un ciclo. AVX2 opera sobre vectores de 256 bits — 8 valores fp32 a la vez. AVX-512 duplica eso a 16 fp32 a la vez (no presente en el i5-8250U).

De aquí viene el número "100 GFLOPS" en una CPU: reloj × cores × fp32_por_AVX × factor_FMA. Para un i5-8250U:

3.4 GHz × 4 cores × 8 fp32/AVX2 × 2 (fused multiply-add cuenta como 2 FLOPs)
≈ 218 GFLOPS  (pico, AVX2 con limitación térmica)

El sostenido es menor porque las cargas AVX2 hacen thermal-throttle en la serie U. El Lab 03 mide el techo real en este ordenador.

Dónde entran en escena las caches

Todo lo anterior corre en fracciones de un nanosegundo. La RAM principal está a ~70 ns. Sin caches, la CPU pasaría el 99% de su tiempo esperando a la memoria. Las caches son la respuesta. Por eso la Fase 1 dedica dos archivos completos de teoría a la jerarquía de memoria.

Eso es theory/02-memory-hierarchy.md. Léelo a continuación.

Recapitulación en un párrafo

Una CPU son miles de millones de transistores organizados en ALUs y lógica de control, dirigidos por un reloj a velocidades de GHz, organizados en un pipeline que solapa fetch / decode / execute / write-back a través de muchas instrucciones en vuelo. Predice saltos, ejecuta fuera de orden, corre instrucciones vectoriales SIMD, y tiene múltiples cores. Cada optimización de rendimiento que toca el currículo asume este ordenador.


Siguiente: theory/02-memory-hierarchy.md.