English · Español
Lab 03 — Roofline de GPU: plot y ubicación de operadores¶
Objetivo: plotear el roofline multi-dtype para la GPU alquilada usando picos medidos (de los labs 01 + 02 + un benchmark fresco de cuBLAS GEMM). Sitúa los operadores de decode de la Fase 22 sobre él.
Tiempo estimado: 90–120 minutos.
Prerrequisito: labs 00, 01, 02 completos. MiniGPT de la Fase 22 funcionando en CPU (con cache).
Lo que produces¶
experiments/23-roofline-gpu/:
peak_flops.py— benchmark de cuBLAS GEMM a través de dtypes.peak_flops.json— TFLOPS pico medidos para fp32, fp16, bf16 (y fp8 si está soportado).decode_attn_gpu.py— porta la decode-attention del MiniGPT de la Fase 22 (un solo paso, solo attention) a arrayscupy; mide latencia e intensidad de cómputo + TFLOPS alcanzados.roofline.png— el plot.roofline.json— todos los datos que alimentan el plot.interpretation.md— 3 párrafos.
Los benchmarks¶
Bloque A — pico de FLOPS medido vía cuBLAS GEMM¶
Para cada dtype en {fp32, fp16, bf16} (y fp8 si compute capability ≥ 9.0):
- Corre
cupy.matmul(A, B)para matrices cuadradas 4096 × 4096 (lo bastante grandes para ser compute-bound). - Warm up 3 iters, después 100 iters cronometradas.
- Registra los TFLOPS medidos. Compara con el pico del fabricante de
device_query.json. Espera 70–90% del pico del fabricante — eso es cuBLAS haciendo trabajo real cerca del límite del hardware.
Si lo medido < 50% del pico del fabricante: investiga. Sospechosos habituales: - Matriz demasiado pequeña (prueba 8192 × 8192 si la HBM lo permite). - Clock boost no enganchado (carga la GPU con trabajo sostenido y re-mide). - Camino de cuBLAS equivocado (Tensor Core vs CUDA core); cuBLAS elige por heurística y puede acertar mal.
Bloque B — decode-attention de la Fase 22 sobre GPU¶
- Carga los pesos del MiniGPT de la Fase 17 desde disco al host, después al device (
cupy.asarray). - Porta el camino forward de attention: cachea K, V en arrays
cupy; la query es el hidden state de un único token. - Para S en {128, 256, 512, 1024}:
- Pre-llena la cache con S entradas aleatorias K, V.
- Cronometra 100 pasos de decode (attention de un único token contra cache de tamaño S).
- Sincroniza antes/después de cronometrar.
- Calcula: latencia por paso (ms), FLOPs por paso (de la teoría en
phase-22/theory/03), bytes por paso (también de la teoría). Intensidad = FLOPs / bytes. TFLOPS alcanzados = FLOPs / tiempo.
La Fase 22 decía intensidad ≈ 0.5–1.0 FLOPs/byte (dependiente de dtype). En GPU con cache fp32: I = 0.5. Con cache fp16 (si haces cast a fp16 primero): I = 1.0.
Bloque C — plot¶
- eje x: intensidad aritmética (log).
- eje y: TFLOPS (log).
- Líneas de techo:
- Pico CUDA core fp32 (medido, no del datasheet).
- Pico Tensor Core fp16 (medido).
- Pico Tensor Core bf16 (medido).
- Pendiente de ancho de banda HBM (D2D medido del lab 02).
- Puntos de operadores:
- cuBLAS GEMM en 4096×4096 fp16 (pico medido, intensidad ≈ 2048).
- cuBLAS GEMM en 4096×4096 fp32 (medido).
- decode-attention fp32 de la Fase 22 (intensidad 0.5, alcanzado del Bloque B).
- decode-attention fp16 de la Fase 22 (intensidad 1.0, alcanzado).
- Anota la fracción de pico junto a cada punto del operador.
Bloque D — interpretar en interpretation.md¶
Tres párrafos:
- ¿Dónde aterrizan los puntos de cuBLAS? ¿Justo en el techo correspondiente? ¿Dentro del 10–20% del techo? Esto valida que el diagnóstico del roofline es real — cuBLAS a tamaños grandes satura el pico del dtype.
- ¿Dónde aterrizan los puntos de decode-attention? Profundamente en la pendiente de memoria (como predijo la teoría de la Fase 22). ¿Qué fracción del pico Tensor Core fp16 estás alcanzando? Debería ser ~0.3–1% — exactamente el diagnóstico "decode es 1% del pico".
- Compara con el roofline de CPU de la Fase 1. ¿Cuál es el ratio de TFLOPS alcanzados en el mismo operador (decode-attention)? ¿Es el ratio de los anchos de banda HBM-a-DRAM (en torno a 100×)? ¿O menor (overhead factor-constante de PCIe, lanzamiento de kernel, etc.)?
TODOs (consolidados)¶
- Bloque A:
peak_flops.py,peak_flops.json, comparación con el pico del fabricante. - Bloque B:
decode_attn_gpu.py, mediciones de latencia en S in {128, 256, 512, 1024}. - Bloque C:
roofline.pngcon todos los techos + puntos + anotaciones. - Bloque D:
interpretation.mdcon 3 párrafos. - Manifest en
experiments/23-roofline-gpu/manifest.json.
Restricciones¶
- Solo
cupy. Aún no PyTorch. (Plan §7.g.) - Cronometra solo después de
deviceSynchronize. Tanto antes como después del bloque cronometrado. - Usa picos medidos, no picos del datasheet, para las líneas de techo.
- No incluyas el tiempo de escritura de la cache en la medición de decode-attention. Ése es un operador separado; estamos midiendo solo el attention.
Condiciones de parada¶
Listo cuando:
- cuBLAS GEMM medido en 3+ dtypes, todos dentro del 30% del pico del fabricante.
- decode-attention medido en 4+ valores de S, ploteado en el roofline.
roofline.pngcommiteado con todos los techos y puntos.interpretation.mdresponde las tres preguntas.manifest.jsoncompleto.
Trampas¶
cupy.matmulpuede elegir el camino fp32 para inputs fp16 según la versión de cuBLAS. Fuerza el dtype asegurándote de que ambos inputs sean del mismo dtype y verifica el kernel realmente usado (víanvprofoncusi están disponibles; si no, fíate del número de throughput).- decode-attention es tan memory-bound que el cronometrado es ruidoso. Cada medición es corta. Corre 1000 iteraciones y reporta mediana, no media.
- Tamaños de matriz demasiado grandes pueden derramarse a HBM si el working set excede L2. Elige tamaños donde tengas claro qué tier estás testeando.
- Vigilancia de coste. Este lab puede consumir 1–2 horas de cloud-GPU. Vigila el presupuesto.
Cuándo consultar solutions/¶
Tras cumplir todas las condiciones de parada. La referencia en solutions/03-gpu-roofline-ref.md muestra los números esperados para la GPU de referencia.
Siguiente: PHASE_23_REPORT.md. La fase está terminada tras report + reflection + un item final de "instancia terminada, coste total registrado" en el checkpoint.