Skip to content

English · Español

05 — Roofline solo-CPU sobre el i5-8250U, y cómo la GPU desplaza el techo

🇪🇸 Antes de hablar de GPU, medimos el techo del único hardware que Borja tiene a mano (Intel i5-8250U, 4C/8T). Calculamos FLOPS y ancho de banda, situamos los kernels del mini-GPT en el plot, y vemos qué dimensión cambiaría una A100. La forma del roofline no cambia — los números sí, y mucho.

Esta página es el compañero de profundidad solo-CPU de theory/04-gpu-roofline.md. Ancla la ecuación del roofline de GPU en la CPU concreta que Borja tiene a mano y cuantifica el desplazamiento que produciría una GPU.


El i5-8250U sobre el papel

Desde learners/borja/profile.md:

  • Arquitectura: Kaby Lake R (2018), Intel Core i5-8250U.
  • Cores / threads: 4 cores / 8 threads.
  • Reloj base / turbo: 1.6 GHz base / 3.4 GHz turbo (single-core).
  • Cache L1d: 32 KiB / core, 8-way.
  • Cache L2: 256 KiB / core, 4-way.
  • Cache L3: 6 MiB compartida.
  • Memoria: DDR4-2400, dual channel, 19.2 GB/s pico teórico.
  • AVX2: sí (SIMD de 256 bits).
  • AVX-512: no.

Calculando el pico de FLOPS

Un core Kaby Lake R puede:

  • 2 unidades fused multiply-add (FMA) por core.
  • Cada FMA maneja AVX2 de 256 bits = 8 floats de precisión simple o 4 de precisión doble.
  • FMA es "2 FLOPs por elemento" (1 mul + 1 add).

Pico de throughput fp32 por core:

\[\pi_\text{core,fp32} = 2 \text{ FMAs} \times 8 \text{ floats} \times 2 \text{ FLOPs/float} \times 3.4 \text{ GHz} = 108.8 \text{ GFLOPS}\]

Para 4 cores a turbo sostenido (~2.8 GHz bajo carga, no all-core turbo):

\[\pi_\text{chip,fp32} \approx 4 \times 2 \times 8 \times 2 \times 2.8 \text{ GHz} \approx 358 \text{ GFLOPS}\]

En la práctica, el throttling de frecuencia AVX2 y los límites térmicos en una CPU U-series bajan esto a ~250-300 GFLOPS sostenidos. Llamémoslo \(\pi \approx 250\) GFLOPS para nuestro roofline.

Para fp64, divide a la mitad el número de carriles: \(\pi_\text{fp64} \approx 125\) GFLOPS.

Para bf16/fp16, el i5-8250U no tiene soporte nativo (no AVX-512-BF16, no AMX). La emulación por software corre a throughput fp32 o peor — así que \(\pi_\text{bf16} \approx \pi_\text{fp32}\) en el mejor caso, a menudo más lento.

Calculando el pico de ancho de banda

DDR4-2400, dual channel:

\[\beta = 2 \text{ channels} \times 8 \text{ bytes} \times 2400 \text{ MT/s} = 38.4 \text{ GB/s pico}\]

En la práctica, con dos canales de memoria y el overhead del chipset, las lecturas streaming sostenidas miden 15-19 GB/s en esta clase de CPU. Llamémoslo \(\beta \approx 16\) GB/s para nuestro roofline.

Balance de la máquina

\[\text{balance de la máquina} = \pi / \beta = 250 \text{ GFLOPS} / 16 \text{ GB/s} = 15.6 \text{ FLOPs/byte}\]

El cruce: un operador con intensidad aritmética por debajo de ~16 FLOPs/byte está limitado por memoria en esta CPU; por encima, está limitado por cómputo.

Dónde aterrizan los operadores del mini-GPT

Recuerda el mini-GPT de la Fase 17: \(d_\text{model} = 64, n_\text{heads} = 4, d_h = 16, L = 2, d_\text{ff} = 256\).

Embedding lookup

Operación: gather de \(T\) filas de una tabla \((V, d_\text{model}) = (512, 64)\).

  • FLOPs: 0 (es una operación de memoria).
  • Bytes: \(T \times d_\text{model} \times s = T \cdot 64 \cdot 4 = 256 T\) bytes.
  • Intensidad aritmética: 0 FLOPs/byte. Puro memory-bound. En el roofline esto se sitúa en el techo de ancho de banda en \(I = 0\), el rendimiento se limita a \(\beta = 16\) GB/s. Generar un token requiere leer 256 B; eso son \(16 \times 10^9 / 256 = 6.25 \times 10^7\) tokens/s si está memory-bound — muchísimo más de lo que necesitamos.

Capa Linear (proyección Q, \(d_\text{model} \to d_\text{model}\))

Para un forward pass de un solo token:

  • Op: matmul \((1, d_\text{model}) \times (d_\text{model}, d_\text{model})\).
  • FLOPs: \(2 \cdot 1 \cdot 64 \cdot 64 = 8192\) FLOPs.
  • Bytes (pesos + input + output): \(64 \cdot 64 \cdot 4 + 64 \cdot 4 + 64 \cdot 4 \approx 16{,}896\) bytes (los pesos dominan).
  • Intensidad aritmética: \(8192 / 16{,}896 \approx 0.48\) FLOPs/byte. Memory-bound. Rendimiento limitado a \(\sim 0.48 \times 16 \text{ GB/s} = 7.7\) GFLOPS.

Para un batch de \(B\) tokens:

  • FLOPs: \(2 \cdot B \cdot 64 \cdot 64 = 8192 B\).
  • Bytes: \(64 \cdot 64 \cdot 4 + B \cdot 64 \cdot 4 + B \cdot 64 \cdot 4 = 16384 + 512 B\).
  • Intensidad aritmética: \(8192 B / (16384 + 512 B)\).
  • En \(B = 8\): \(65{,}536 / (16384 + 4096) = 65{,}536 / 20480 \approx 3.2\) FLOPs/byte. Aún memory-bound.
  • En \(B = 128\): \(\approx 11.0\) FLOPs/byte. Acercándose a compute-bound pero todavía no.

Por eso la inferencia por batch es mucho más eficiente que muestra a muestra: amortizar la carga de pesos entre muchos tokens eleva la intensidad aritmética.

Score de atención \(QK^T\)

Para una secuencia de \(S\) tokens, \(H = 4\) heads:

  • Op: \((S, d_h) \times (d_h, S)\) por head.
  • FLOPs por head: \(2 \cdot S \cdot d_h \cdot S = 2 S^2 d_h\).
  • Bytes por head: \(2 S \cdot d_h \cdot s\) (leer Q, K) + \(S^2 \cdot s\) (escribir scores) = \(S \cdot d_h \cdot 2s + S^2 \cdot s\).
  • En \(S = 64, d_h = 16, s = 4\): FLOPs \(= 2 \cdot 4096 \cdot 16 = 131{,}072\); bytes \(= 64 \cdot 16 \cdot 8 + 4096 \cdot 4 = 8192 + 16384 = 24576\). IA \(= 131{,}072 / 24576 \approx 5.3\) FLOPs/byte. Memory-bound en el i5-8250U.

Diagrama de roofline (mental)

       250 GFLOPS  ── ── ── ── ── ── ── ── ── ── ──┐   techo de cómputo
                                        ╱   ←─── Linear, B=128
                            ╱   ←─── Attention, S=64
                ╱   ←─── Linear, B=8
    ╱   ←─── Linear, B=1 (memory-bound)
       I = 0.48

Todo kernel significativo en el i5-8250U está a la izquierda del cruce de balance de la máquina. Todo kernel está memory-bound. La CPU tiene 250 GFLOPS pero los kernels solo pueden extraer 1-20 GFLOPS de eso debido al ancho de banda de memoria.

Cómo la GPU desplaza el roofline

Una NVIDIA A100 (objetivo de las Fases 23-24):

  • \(\pi_\text{fp32}\) = 19.5 TFLOPS = ~78× el i5-8250U.
  • \(\pi_\text{fp16}\) = 312 TFLOPS (Tensor Cores) = ~1250× el fp32 del i5-8250U.
  • \(\beta\) = 1.5 TB/s = ~94× el i5-8250U.
  • Balance fp32: \(19500 / 1500 = 13\) FLOPs/byte (similar al i5-8250U).
  • Balance fp16 con Tensor Cores: \(312000 / 1500 = 208\) FLOPs/byte (mucho más alto).

Qué significa esto:

  1. Para GEMMs fp32, el balance de la máquina es similar en CPU y GPU — los operadores que están memory-bound en CPU siguen memory-bound en GPU, pero el throughput absoluto es ~100× más alto.
  2. Para GEMMs fp16 con Tensor Cores, el balance de la máquina es mucho más alto — los operadores que eran compute-bound pasan a ser memory-bound bajo la nueva proporción. Para mantenerte compute-bound sobre Tensor Cores, necesitas intensidad aritmética de 200+ FLOPs/byte, lo que implica productos muy grandes de batch × seq × hidden.
  3. La forma del roofline no cambia — misma ecuación, \(\min(\pi, I \beta)\). Solo los techos y el cruce.

Benchmark práctico que Borja debe correr

El lab 02-bandwidth-test.md de la Fase 23 corre STREAM sobre el i5-8250U. Salida esperada: ~15-18 GB/s en el benchmark Triad. Compara contra el pico teórico de 19.2 GB/s y obtienes la fracción alcanzable (~80-90%).

Luego corre un benchmark de matmul fp32 single-thread sobre una matriz \(1024 \times 1024\). Esperado: 3-5 GFLOPS sostenidos (muy por debajo del pico single-core de 108 GFLOPS — porque el matmul a este tamaño no cabe en L1, así que se derrama a memoria y pasa a ser memory-bound). Sobre una matriz \(128 \times 128\) (cabe en L1), espera 30-50 GFLOPS.

Estos dos números — ancho de banda de STREAM, GFLOPS de matmul in-cache — son tu roofline de CPU. Plotea el matmul en múltiples tamaños; la curva traza el roofline.

La lección §A13

Todo kernel del mini-GPT §A13 vive en la región memory-bound del roofline de CPU. Podríamos correr sobre una GPU y los kernels seguirían siendo memory-bound (relativos al techo de GPU mucho más alto). El microscopic scope te deja ver esto con claridad sin la complejidad de modelos grandes. Cuando pases a escala GPT-3 en los labs cloud de la Fase 23+, verás que los mismos kernels se comportan de forma fundamentalmente distinta — dimensiones ocultas grandes empujan la intensidad aritmética hacia el régimen compute-bound, y los Tensor Cores extraen órdenes de magnitud más de throughput.

El punto de esta página: mides el roofline de CPU a mano una vez, y la metodología no cambia. Solo las constantes.

Cita

Williams, S., Waterman, A., & Patterson, D. (2009). Roofline: An Insightful Visual Performance Model for Multicore Architectures. CACM 52(4), 65-76. El artículo original del roofline. La Fase 1 lo citó para CPU; la Fase 23 lo cita de nuevo para GPU. Misma ecuación.

Resumen en un párrafo

El i5-8250U tiene \(\pi \approx 250\) GFLOPS (fp32, AVX2 sobre 4 cores) y \(\beta \approx 16\) GB/s (DDR4-2400 dual channel), dando un balance de máquina de ~16 FLOPs/byte. Todo kernel del mini-GPT §A13 vive a la izquierda de este cruce — Linear en \(B = 1\) tiene IA = 0.48 FLOPs/byte, Linear en \(B = 128\) llega a ~11. La GPU A100 tiene \(\pi\) ~78× más alto y \(\beta\) ~94× más alto; el balance fp32 es similar, así que los mismos kernels permanecen memory-bound con throughput absoluto enormemente mayor. La ecuación del roofline es invariante entre CPU y GPU; solo cambian las constantes.


Referencias cruzadas: theory/04-gpu-roofline.md (la misma ecuación con constantes de GPU), Fase 1 theory/03-roofline-model.md (la derivación original para CPU), lab/02-bandwidth-test.md (el benchmark STREAM que corres sobre el i5).