Skip to content

English · Español

Lab 00 — Roofline en tres aceleradores

🇪🇸 La misma multiplicación de matrices en CPU, A100 y H100. Verás cómo cambia el techo, cómo cambia tu kernel, y qué tan lejos estás del pico en cada uno.

Objetivo

Para el mismo kernel matmul FP16 (\(M = N = K = 8192\)), mide los FLOPS alcanzados y el bandwidth HBM/RAM en tres aceleradores distintos. Traza los tres sobre un roofline unificado. Explica la brecha al pico en cada uno.

Esta es la generalización directa del lab roofline de la Fase 01 al hardware GPU. El modelo mental es el mismo; los números son 10000× mayores.

Prerrequisitos

  • Lab roofline de la Fase 01 completado (experiments/01-roofline/ existe con números del i5-8250U).
  • Una cuenta de runpod.io (o lambda.ai, o vast.ai).
  • PyTorch 2.4+ instalado localmente (para el baseline CPU) y disponible en las imágenes de alquiler.

Targets de hardware

Target Proveedor SKU sugerida Coste por hora (2025) Tiempo de corrida Coste total
Intel i5-8250U Local (portátil de Borja) ya hecho en la Fase 01 $0
NVIDIA A100 80 GB SXM4 RunPod "A100 SXM 80GB" (Community Cloud) ~$1.50/h ~30 min ~$0.80
NVIDIA H100 80 GB SXM5 RunPod "H100 SXM 80GB" (Community Cloud) ~$3.00/h ~30 min ~$1.50

**Coste total en la nube: ~\(2.30** (con 1 h de margen presupuestario: techo ~\)5).

Proveedores alternativos (usa el que tenga mejor disponibilidad):

  • lambda.ai — A100 ~\(1.10/h on-demand, H100 ~\)2.49/h.
  • vast.ai — variable, a menudo el spot más barato.

Script de setup (para el pod en la nube)

Tras hacer SSH al pod:

# 1. Verify hardware.
nvidia-smi
# Expect: "NVIDIA A100-SXM4-80GB" or "NVIDIA H100 80GB HBM3"; ~80 GB / ~141 GB depending on SKU.

# 2. Verify PyTorch CUDA build.
python -c "import torch; print(torch.__version__, torch.cuda.is_available(), torch.cuda.get_device_name(0))"

# 3. Clone your work.
git clone <your-fork-of-lynx-cortex>
cd lynx-cortex
uv sync

El kernel bajo prueba

Un único matmul FP16 denso. La misma forma en cada acelerador para comparabilidad directa.

# experiments/x4-roofline/matmul_bench.py  (reference structure; learner writes the body)
import torch, time, json, sys
from pathlib import Path

def bench_matmul(M=8192, N=8192, K=8192, dtype=torch.float16, device="cuda", warmup=5, iters=20):
    """
    Returns (achieved_TFLOPS, achieved_GBps_one_way) for a single matmul.

    Notes for learner:
    - Use torch.cuda.Event with synchronize for GPU timing; time.perf_counter is wrong on GPU.
    - Total FLOPs for matmul: 2 * M * N * K (one mul + one add per element of C).
    - Bytes moved per op (lower bound): (M*K + K*N + M*N) * dtype.itemsize. This is the
      ideal-cache estimate; real HBM traffic can be higher.
    - Arithmetic intensity = 2*M*N*K / bytes_moved.
    """
    # TODO (learner): implement.
    ...

El aprendiz escribe el cuerpo. El test autoevaluado en tests/extension/X4/test_lab00_bench.py comprueba que la función devuelve números sensatos (dentro de una banda de tolerancia) en cualquier dispositivo CUDA que ejecute el test.

Qué medir

Para cada dispositivo, registra:

Métrica Cómo
Pico FP16 TFLOPS (vendor) Del datasheet (ver tabla en theory/01)
Pico de bandwidth HBM/RAM (vendor) Del datasheet
TFLOPS alcanzados (tu kernel) 2*M*N*K / median_time
Bandwidth alcanzado bytes_moved / median_time
Intensidad aritmética 2*M*N*K / bytes_moved (≈ 4096 para K=8192 cubo — muy por encima de cualquier cresta de roofline)
MFU (model FLOPS utilization) alcanzado / pico FP16

Resultados esperados (tabla de sanidad)

Estos son los números que debes obtener con ±20%. Si te sales mucho, sospecha de un bug de benchmarking (sin warmup, sin cuda.synchronize, recuento de FLOP equivocado).

Dispositivo Pico FP16 (TF/s) Pico BW (TB/s) TF/s esperados MFU esperado
i5-8250U (CPU, FP32 vía MKL) ~0.17 ~0.019 ~0.10-0.15 60-85%
A100 80 GB (FP16) 312 2.0 230-280 75-90%
H100 80 GB (FP16) 989 3.35 700-850 70-85%

[fuente: guía de rendimiento de NVIDIA cuBLAS 2023; microbenchmarks de matmul de MLPerf Inference]

Por qué estos valores MFU:

  • La CPU (BLIS / MKL gemm) está extremadamente bien sintonizada; MKL en Kaby Lake entrega ~80% del pico.
  • A100 con cuBLAS alcanza ~85% en matmuls bien formados.
  • La H100 es ligeramente más difícil de saturar en FP16 sin usar FP8 + Transformer Engine; cuBLAS obtiene ~75-85% en este tamaño.

Si quieres llevar la H100 más lejos, cambia a FP8 vía transformer_engine.pytorch.Linear — deberías ver ~1500 TF/s (aún por debajo del pico de 1979, pero más cerca).

Gráfica del roofline

Traza los tres dispositivos en un único plot log-log:

  • Eje x: intensidad aritmética (FLOP/byte).
  • Eje y: rendimiento (FLOP/s).
  • Para cada dispositivo, dibuja la línea de memoria (pendiente = BW) y el techo de cómputo (horizontal en el pico FLOPS).
  • Coloca tu kernel como un punto por dispositivo.

Para un matmul FP16 \(8192^3\), la intensidad aritmética está muy por encima de la cresta de cada dispositivo, así que los tres puntos deberían caer cerca del techo de cómputo. Si caen por debajo, esa es una historia que contar: ¿qué perilla falta?

Explicación de la brecha (el aprendizaje real)

Para cada dispositivo, escribe 3-5 oraciones explicando la brecha entre lo alcanzado y el pico. Respuestas esperadas:

  • CPU: límite de throughput AVX2-FMA; el camino L3 → registro está saturado; el block-packing de MKL deja un pequeño porcentaje sobre la mesa.
  • A100: overhead de lanzamiento por llamada de cuBLAS; el kernel no usa TF32 (la spec es FP16); el write-back HBM2e de C es inevitable.
  • H100: cuBLAS en FP16 no usa el nuevo camino del Transformer Engine FP8; la nueva instrucción asíncrona WGMMA necesita programación explícita para explotarse al máximo; FP16 es "modo lento" en la H100.

La intuición de grado de entrevista: las brechas son normales y te dicen qué perilla girar. Pasar la CPU de naive → MKL es 100×. Pasar la H100 de FP16 cuBLAS → FP8 Transformer Engine es otro 1.5-2×.

Entregables

  • experiments/x4-roofline/manifest.json — versiones fijadas, seeds, SKUs, coste por hora.
  • experiments/x4-roofline/results.csv — una fila por (dispositivo, dtype, forma, achieved_tflops, achieved_bw_gbps, mfu).
  • experiments/x4-roofline/roofline.png — el plot de tres dispositivos.
  • experiments/x4-roofline/REPORT.md — 1 página narrando las brechas.

Definition of Done

  • Los tres dispositivos medidos.
  • TFLOPS FP16 alcanzados en H100 ≥ 600 (es decir, MFU ≥ 60%).
  • TFLOPS FP16 alcanzados en A100 ≥ 200 (es decir, MFU ≥ 65%).
  • El plot roofline está en el directorio de artefactos y renderizado en el informe.
  • El párrafo de explicación de la brecha es concreto (cita la optimización ausente), no genérico.

Enlaces cruzados

Referencias

  • Williams S., Waterman A., Patterson D. 2009, Roofline: An Insightful Visual Performance Model for Multicore Architectures, CACM.
  • NVIDIA cuBLAS Performance Guide, 2023.
  • NVIDIA H100 Tuning Guide, 2023.