Skip to content

English · Español

Lab 00 — Presupuesto cloud, encuesta de proveedores y guard de presupuesto

Objetivo: antes de tocar cualquier GPU cloud, anota lo que vas a gastar y fuérzalo programáticamente. La Fase 35 es la única fase con coste cloud real. Pilla bien la disciplina primero.

Tiempo estimado: 60–90 minutos.

Prerrequisito: nada de la Fase 35 todavía. Borja ha leído teoría 00–04.


Qué produces

Un único directorio commiteado en experiments/35-cloud-budget/ que contenga:

  • vendor-survey.md — snapshot de precios al momento del lab, tres proveedores comparados, elección recomendada con un párrafo de justificación.
  • budget.md — el techo duro de $5, dividido en topes por lab con margen.
  • pre-flight-checklist.md — la rutina a ejecutar antes de cada spinup cloud (chequeo de presupuesto, confirmación del tipo de instancia, alarma de tope de tiempo, plan de terminación).
  • manifest.json{seed, lab, hardware_target, vendor, currency, ceiling_usd} para reproducibilidad.

Más una pequeña pieza de código en la extensión ya existente del currículo a src/minitrain/ (según el plan A12 — la Fase 35 no introduce un nuevo módulo top-level):

  • src/minitrain/budget_guard.py — una clase BudgetGuard que lee LYNX_CLOUD_BUDGET_USD (env var) y un log de gasto en curso en experiments/35-cloud-budget/spend.jsonl, rechazando lanzar cualquier operación cuyo coste estimado rompería el techo.

El guard no es un SDK a un proveedor cloud — es un wrapper local de enforcement alrededor de subprocess.run(["runpodctl", ...]) o equivalente. Loguea el coste estimado a la entrada y el coste real a la salida.

TODOs

Bloque A — encuesta de proveedores

Elige tres proveedores plausibles para un job de 2-GPU en burst corto y haz snapshot de los precios de hoy:

  • RunPod (https://www.runpod.io) — spot 2× GPUs consumer (RTX 4090, RTX 6000 Ada) — registra $/hr por GPU.
  • Lambda Labs (https://lambdalabs.com) — on-demand 2× A100 o 2× A6000 — registra $/hr por GPU.
  • Vast.ai (https://vast.ai) — community spot 2× GPUs consumer — registra $/hr por GPU.

Para cada uno: coste horario por GPU, memoria disponible, notas de ancho de banda de red, y si hay NVLink entre las 2 GPUs en el mismo nodo. NVLink importa para TP (la matemática de ancho de banda del fichero de teoría 03).

Regla de recomendación: elige el tier spot más barato que tenga NVLink entre el par si está disponible, si no el tier spot más barato con ubicación 2-GPU single-node garantizada. Documenta la elección en un párrafo.

Bloque B — desglose del presupuesto

Asigna el techo de $5 entre los tres labs que usan cloud:

Lab 02 (inferencia TP, 2-GPU)       ≤ $3.00
Lab 03 (lectura Megatron+FSDP)      = $0.00 (sin cloud)
Buffer para retries / setup tax     ≤ $2.00
─────────────────────────────────────────────
Presupuesto cloud total Fase 35     ≤ $5.00

Escribe esto en budget.md. Incluye razonamiento: "$3 para el lab 02 = 2× RTX 4090 a $0.35/hr cada una × 3 horas = $2.10; redondeado a $3 para 40% de buffer por setup tax, pulls de contenedor, retries."

Bloque C — implementa BudgetGuard

# src/minitrain/budget_guard.py — esqueleto (Borja escribe el cuerpo)

import json
from pathlib import Path
import os

class BudgetGuardExceeded(Exception):
    """Raised when an operation would exceed the budget."""

class BudgetGuard:
    def __init__(self, ceiling_usd: float, log_path: Path):
        ...

    def authorize(self, op_label: str, estimated_usd: float) -> None:
        """Raises BudgetGuardExceeded if estimated total > ceiling. Logs intent."""
        ...

    def record_actual(self, op_label: str, actual_usd: float) -> None:
        """Append actual spend after the operation finishes."""
        ...

    @property
    def total_spent(self) -> float:
        ...

    @property
    def remaining(self) -> float:
        ...

Restricciones:

  • Sin llamadas de red en este módulo. La integración con proveedor cloud está fuera de alcance para el guard en sí; el guard solo lleva la contabilidad. El usuario lo invoca manualmente antes/después de runpodctl create ....
  • Log append-only. experiments/35-cloud-budget/spend.jsonl es la fuente de verdad. Las líneas son {ts, op_label, estimated, actual?, currency}. Nunca editar; nunca borrar.
  • LYNX_CLOUD_BUDGET_USD env var sobreescribe el argumento del constructor si está definida — te permite apretar el techo sin tocar código.

Bloque D — pre-flight checklist

Escribe pre-flight-checklist.md listando los pasos a ejecutar cada vez antes de levantar una instancia cloud:

  1. Chequear consola del proveedor: ¿hay otras instancias corriendo? (Si sí, te olvidaste de terminarlas. Termínalas.)
  2. Poner una alerta de presupuesto en la consola cloud al 80% del tope del lab.
  3. Poner auto-terminación de instancia a 4 horas (lado del proveedor, además de tu propio guard).
  4. BudgetGuard.remaining debe mostrar ≥ coste_estimado + 50% de margen.
  5. Anota el timestamp exacto de inicio; lo restarás de un timestamp final conocido para calcular el coste real.
  6. Tras el lab: confirma que la instancia está terminada vía screenshot de la consola del proveedor; commitea el screenshot a experiments/35-tp-inference/proof-terminated.png.

Bloque E — escribe el manifest

manifest.json:

{
  "seed": 35000,
  "lab": "00-cloud-budget-and-tooling",
  "hardware_target": "to be filled in lab 02",
  "vendor": "<chosen>",
  "currency": "USD",
  "ceiling_usd": 5.00,
  "ceiling_per_lab": {"02": 3.00, "buffer": 2.00},
  "spend_log_path": "experiments/35-cloud-budget/spend.jsonl",
  "vendor_snapshot_date": "<lab date>",
  "vendor_snapshot_prices": {"<vendor>": "<per-gpu $/hr>"}
}

Restricciones

  • Sin spinup cloud en este lab. Este es el lab de preparación. El spinup ocurre solo en el lab 02.
  • El dinero es la frontera. Si en algún momento escribiendo el presupuesto te encuentras pensando "en realidad $5 es demasiado apretado, hagámoslo $20", para y relee el párrafo del presupuesto de theory/00-motivation.md. El objetivo es aprender paralelismo distribuido con presupuesto de aprendiz. Si genuinamente necesitas un presupuesto mayor, esa es una conversación a nivel de currículo con el equipo amplio.
  • Preemption de tier spot. Las instancias spot pueden ser recuperadas por el proveedor con 30 s de aviso. Planifica para esto: el experimento del lab 02 debe guardar resultados parciales tras cada medición para que un preempt no malgaste la corrida.

Condiciones de parada

Has acabado cuando:

  1. experiments/35-cloud-budget/{vendor-survey,budget,pre-flight-checklist,manifest.json}.md existen todos.
  2. src/minitrain/budget_guard.py existe, tiene tests en tests/minitrain/test_budget_guard.py, y pytest tests/minitrain/test_budget_guard.py pasa (con BUDGET_GUARD_TEST_MODE=1 para desactivar escrituras a disco).
  3. BudgetGuard.authorize("lab02-tp-spinup", 3.00) tiene éxito en un test rápido de REPL; BudgetGuard.authorize("hypothetical-lab", 10.00) levanta BudgetGuardExceeded.
  4. La pre-flight checklist se lee como algo que una persona cansada podría ejecutar mecánicamente.

Pista de último recurso

Si tras 60 minutos estás atascado con los precios del proveedor — los precios se mueven semana a semana, este lab acabará desactualizado — usa un placeholder agnóstico de proveedor: "Asumimos 2× GPU consumer a $0.35/hr por GPU = $0.70/hr total. El lab 02 corre ≤ 3 horas = $2.10. Techo de presupuesto: $3.00 con 40% de buffer." Anota la suposición explícitamente en vendor-survey.md. Sigue adelante.

Cuándo consultar solutions/

Tras haber commiteado los ficheros de presupuesto y BudgetGuard. La solución vive en solutions/00-cloud-budget-ref.md — escrita en la apertura de la fase con los precios actuales de proveedores. Compara; no leas antes.


Siguiente lab: lab/01-ddp-on-cpu.md.