⏱️ Lectura: 13 min

Meta y AMD acaban de resolver uno de los problemas más caros del entrenamiento de modelos de lenguaje a gran escala: qué hacer cuando un nodo se cae a mitad de un trabajo que lleva días corriendo. La respuesta se llama PyTorch Monarch, y desde el 6 de julio de 2026 también corre en GPUs AMD Instinct con ROCm, no solo en hardware NVIDIA con CUDA.

📑 En este artículo
  1. TL;DR
  2. Introducción
  3. Qué pasó
  4. Contexto e historia
  5. Detalles técnicos y rendimiento
  6. Cómo empezar
    1. Linux con ROCm (ruta soportada)
    2. macOS (sin GPU AMD real)
    3. Windows
  7. Impacto y análisis
  8. Qué sigue
  9. Preguntas frecuentes
    1. ¿Qué es PyTorch Monarch?
    2. ¿Por qué era necesario portarlo a ROCm?
    3. ¿Qué significa single-controller en este contexto?
    4. ¿Monarch reemplaza a NCCL o RCCL?
    5. ¿Se puede usar Monarch fuera de Meta hoy?
    6. ¿Qué diferencia hay entre un checkpoint tradicional y la recuperación de Monarch?
  10. Referencias

Antes de este port, un error de memoria en una sola GPU forzaba reiniciar el cluster completo desde el último checkpoint. Con Monarch, los nodos sanos siguen entrenando mientras el nodo caído se recupera y vuelve a sumarse al trabajo, sin perder el progreso acumulado.

TL;DR

  • AMD y Meta portaron PyTorch Monarch a GPUs Instinct con ROCm, ampliando el runtime más allá de CUDA, según el anuncio del 6 de julio de 2026.
  • El port usa hipify_torch para convertir el puente C++ de CUDA a HIP y enlaza contra RCCL en vez de NCCL.
  • El runtime en Rust corre sobre Tokio y coordina actores, mallas de procesos (process mesh) y sharding de tensores.
  • ROCm no tiene equivalente estático a libcudart_static.a: Monarch enlaza amdhip64 de forma dinámica en vez de estática.
  • El modelo jerárquico de fallos aísla crashes por actor: la recuperación local toma segundos, no minutos.
  • La integración RDMA se mantiene sobre libibverbs; con GPU_PLATFORM=rocm solo cambian los bindings GPU de CUDA a HIP.
  • El trabajo previo de AMD ya había logrado 96,16% de eficiencia de escalado en un cluster de 1024 GPU MI325 entrenando DeepSeek-V3-671B.

Introducción

PyTorch Monarch es un runtime experimental que le permite a un solo programa en Python orquestar cientos o miles de GPUs a la vez, como si fueran una sola máquina. En vez de escribir código distribuido explícito para cada nodo, el desarrollador escribe un script secuencial y Monarch se encarga de repartirlo, ejecutarlo en paralelo y recuperarlo si algo falla.

El anuncio conjunto de AMD y Meta del 6 de julio de 2026 documenta cómo se portó el runtime de GPU y la pila de comunicación distribuida de Monarch desde CUDA hacia ROCm, la plataforma de cómputo de AMD para sus aceleradores Instinct. Es la primera vez que el modelo de single-controller de Monarch sale del ecosistema NVIDIA.

Qué pasó

El equipo de ingeniería de AMD (Chaojun Hou, Liz Li, Zachary Streeter, Xinyu Kang, Lei Zhang, Yuankai Chen, Yao Fu, Wen Chen, Zhenyu Gu y Andy Luo), junto al equipo de Monarch en Meta (Matthias Reso, Hamid Shojanazeri y colaboradores), publicaron el port completo en el blog oficial de PyTorch el 6 de julio de 2026.

El trabajo tocó tres capas distintas del stack:

  • Comunicaciones colectivas. Usaron la herramienta hipify_torch para convertir automáticamente el puente C++ de CUDA a HIP, y enlazaron el resultado contra RCCL, la librería de AMD que replica la API de NCCL.
  • Gestión de memoria de GPU. Extendieron el sistema de build para detectar la plataforma en tiempo de compilación y redirigir cada llamada al driver de CUDA hacia su equivalente HIP.
  • Integración RDMA. Con la variable GPU_PLATFORM=rocm, el camino de RDMA basado en libibverbs queda intacto; lo único que cambia son los bindings de GPU, de CUDA a HIP, para las transferencias GPU-direct.

Dos decisiones de diseño destacan del port. Primero, ROCm no tiene equivalente estático a libcudart_static.a: mientras CUDA enlaza cudart_static directamente, el build de ROCm enlaza amdhip64 de forma dinámica, y ambas plataformas usan dlopen para las funciones del driver GPU (hipMemCreate, cuMemCreate y afines), lo que mantiene el mismo contrato de runtime en los dos lados.

Segundo, en vez de mantener dos versiones distintas de los bindings de Rust, el equipo dejó que hipify_torch reescribiera los headers C/C++ y que bindgen generara automáticamente los tipos con nombres HIP (hipError_t, hipDeviceptr_t, hipStream_t). Un compatibility shim en Rust unifica esos tipos con sus equivalentes CUDA, así que existe un único código fuente en vez de dos forks divergentes.

💡 Tip: si compilás Monarch desde el código fuente, la variable GPU_PLATFORM=rocm es el único interruptor que necesitás tocar: el resto de la detección de plataforma es automática en el build system.

Contexto e historia

El problema que Monarch ataca no es nuevo. El checkpointing periódico, guardar el estado completo del modelo en almacenamiento cada cierto intervalo, es la estrategia estándar de tolerancia a fallos en entrenamiento distribuido. Funciona, pero tiene un costo que crece con la escala:

Problema del checkpointing tradicionalImpacto
Overhead de escrituraGuardar cientos de gigabytes de estado consume tiempo y ancho de banda de I/O
Cómputo perdidoTodo el progreso desde el último checkpoint se pierde con cada fallo
Cluster ociosoTodo el cluster espera mientras se reemplaza el nodo caído y el trabajo reinicia
Límite de escalabilidadA mayor tamaño del cluster, mayor probabilidad de que un fallo ocurra dentro de cualquier intervalo de checkpoint

Este no es un problema abstracto para AMD y Meta. En un trabajo previo, AMD ya había demostrado un escalado casi lineal de entrenamiento en FP8, con 96,16% de eficiencia de escalado en un cluster de 1024 GPU MI325 entrenando DeepSeek-V3-671B. Escalar el cómputo dejó de ser el cuello de botella: sobrevivir a los fallos, mientras se escala, es lo que faltaba resolver.

La arquitectura de Monarch separa dos cosas que solían estar acopladas: la estrategia de paralelismo dentro de cada réplica de entrenamiento, y el mecanismo de tolerancia a fallos entre réplicas. Esa separación es la que permite aislar un fallo en vez de propagarlo a todo el cluster.

Arquitectura de PyTorch Monarch con capas Python, Rust y GPU
Monarch separa la API en Python del runtime Rust y de la infraestructura de red. Foto de Michael Dziedzic en Unsplash

Detalles técnicos y rendimiento

La arquitectura de Monarch opera en cuatro niveles:

  • API en Python. Una sola interfaz de programa: el desarrollador escribe código Python secuencial y obtiene ejecución distribuida en GPU.
  • Monarch Runtime. Gestiona actores y mallas de procesos (process mesh), árboles de supervisión y el sharding de tensores.
  • Rust Runtime sobre Tokio. Garantiza rendimiento y seguridad de memoria en la capa de ejecución.
  • Infraestructura. Se integra con RDMA, RCCL/NCCL, SLURM, Kubernetes y SkyPilot.

El modelo de actores es la pieza clave. Cada actor tiene estado privado, así que un crash no se propaga automáticamente a otros actores. Los fallos se manejan en el nivel más bajo posible de una jerarquía de supervisión, y la recuperación es rápida: segundos para un reinicio local, minutos solo si el fallo escala hacia arriba en el árbol de supervisión.

flowchart TD
A["API Python"] --> B["Monarch Runtime: actores y process mesh"]
B --> C["Rust Runtime (Tokio)"]
C --> D["RDMA / RCCL / NCCL"]
D --> E[("Cluster GPU AMD Instinct o NVIDIA")]
subgraph Infraestructura
D
E
end

La siguiente tabla resume dónde cambió cada componente al pasar de CUDA a ROCm:

ComponenteRuta CUDA (NVIDIA)Ruta ROCm (AMD)
Comunicaciones colectivasEnlaza directo contra NCCLhipify_torch convierte el puente C++ y enlaza contra RCCL
Gestión de memoria GPULlamadas nativas al driver CUDA (cuMemCreate)El build system redirige a los equivalentes HIP (hipMemCreate)
Integración RDMABindings CUDA sobre libibverbsMismo camino libibverbs, bindings GPU cambiados a HIP
Enlazado del runtimeEstático contra libcudart_static.aSin equivalente estático; amdhip64 se enlaza dinámicamente

⚠️ Ojo: si tu pipeline de build asume un runtime estático tipo CUDA, vas a tener que ajustar el empaquetado: ROCm depende de amdhip64 como librería dinámica, así que el binario final necesita esa dependencia disponible en tiempo de ejecución, no solo en tiempo de compilación.

Cómo empezar

Monarch sigue siendo un proyecto experimental, así que probarlo hoy significa compilarlo desde el código fuente y apuntar el build al backend correcto.

Linux con ROCm (ruta soportada)

# Clonar el repositorio y entrar al directorio
git clone https://github.com/pytorch-labs/monarch.git
cd monarch

# Apuntar el build al runtime de AMD en vez de CUDA
export GPU_PLATFORM=rocm
export ROCM_PATH=/opt/rocm

pip install -e .

macOS (sin GPU AMD real)

ROCm no corre nativamente en macOS. Para trabajar en el código Python de Monarch sin ejecutar kernels reales, instalá el paquete en modo solo-CPU y conectate a un cluster Linux remoto para las corridas de entrenamiento:

pip install -e . --no-deps
# las llamadas a GPU se despachan al cluster remoto via SSH/SLURM

Windows

Windows tampoco tiene soporte nativo de ROCm. La ruta práctica es usar WSL2 con passthrough de GPU (todavía experimental para AMD) o conectarse por SSH a un nodo Linux del cluster de entrenamiento.

Un ejemplo mínimo, un actor con estado que corre localmente:

from monarch.actor import Actor, endpoint, this_proc

class Contador(Actor):
    def __init__(self):
        self.valor = 0

    @endpoint
    def incrementar(self, paso: int) -> int:
        self.valor += paso
        return self.valor

proc = this_proc()
contador = proc.spawn("contador", Contador)
print(contador.incrementar.call(5).get())

Este actor guarda su estado (self.valor) en un proceso aislado. Llamarlo desde el script principal se ve igual que llamar una función normal, aunque por dentro viaje a través del runtime en Rust.

Un ejemplo más cercano a un caso real, un mesh de procesos que sobrevive al fallo de un entrenador:

from monarch.actor import Actor, endpoint
from monarch.mesh import ProcessMesh

class EntrenadorGPU(Actor):
    @endpoint
    def paso_entrenamiento(self, batch):
        return self.modelo.step(batch)

mesh = ProcessMesh.from_slurm(nodos=64, gpus_por_nodo=8)
entrenadores = mesh.spawn("entrenador", EntrenadorGPU)

try:
    resultados = entrenadores.paso_entrenamiento.call(lote_actual).get()
except ActorCrashError as fallo:
    mesh.reemplazar_nodo(fallo.nodo_id)
    resultados = entrenadores.paso_entrenamiento.call(lote_actual).get()

Cuando un actor de EntrenadorGPU se cae, la excepción se captura en el proceso controlador, no en los otros 511 procesos del mesh. El controlador reemplaza el nodo y reintenta ese paso, sin tocar el resto del entrenamiento.

Para confirmar que tu build quedó enlazado contra ROCm y no contra CUDA, revisá las dependencias dinámicas del binario compilado:

ldd $(python3 -c "import monarch, os; print(os.path.dirname(monarch.__file__))")/_monarch_rust*.so | grep -i hip

Si el build es correcto, esa línea debería listar libamdhip64.so. Un build CUDA en cambio mostraría libcudart.so en su lugar.

Impacto y análisis

Para AMD, este port es una pieza más de un objetivo más amplio: que el software de entrenamiento distribuido no dependa de que el cluster sea NVIDIA. Cada framework que se porta a ROCm reduce el costo de cambiar de proveedor de GPU para un equipo de investigación, algo especialmente relevante cuando la demanda de cómputo de IA supera la oferta de GPU disponible.

Para Meta, expandir Monarch más allá de CUDA valida la apuesta por el modelo de single-controller como paradigma general, no como una solución atada a un solo fabricante de hardware. Si el mismo script Python orquesta tanto GPUs NVIDIA como AMD, un equipo de investigación puede moverse entre clusters sin reescribir su lógica de entrenamiento, evaluación y aprendizaje por refuerzo.

Dicho esto, el port tiene límites que vale la pena nombrar. RCCL replica la API de NCCL, pero no es un espejo perfecto: la paridad de rendimiento en cada colectivo (all-reduce, all-gather, reduce-scatter) depende de qué tan optimizada esté cada operación específica en RCCL, y eso puede variar según la topología del cluster. Además, Monarch sigue siendo un runtime experimental: el modelo de actores agrega una capa de indirección que tiene sentido a gran escala, pero es complejidad de más para un entrenamiento de un solo nodo, donde un script tradicional con torch.distributed sigue siendo más simple de depurar.

Cluster de GPUs AMD Instinct conectadas por red RDMA
El camino RDMA sobre libibverbs se mantiene igual entre CUDA y ROCm. Foto de Alexandre Debiève en Unsplash
💭 Clave: la ganancia real de Monarch no es velocidad de cómputo, es utilización del cluster: menos horas de GPU pagadas y ociosas esperando un reinicio.

Qué sigue

AMD y Meta describen este port como un paso para llevar el runtime de Monarch a un ecosistema de hardware más amplio, lo que sugiere que ROCm no será el último backend no-CUDA. El diseño desacoplado entre API en Python, runtime en Rust e infraestructura de red facilita agregar nuevos backends de comunicación sin reescribir la capa que ve el desarrollador.

A corto plazo, lo más probable es que el trabajo se concentre en cerrar la brecha de paridad entre RCCL y NCCL en las operaciones colectivas que más pesan en entrenamiento a gran escala, y en documentar mejor la integración con SLURM y Kubernetes sobre ROCm, dado que ambos orquestadores ya están soportados en la capa de infraestructura de Monarch.

📖 Resumen en Telegram: Ver resumen

Si tenés acceso a un nodo con GPU AMD Instinct y ROCm instalado, cloná el repositorio y corré el ejemplo del actor con GPU_PLATFORM=rocm: te toma menos de diez minutos confirmar si tu setup local ya quedó listo para probar Monarch.

Preguntas frecuentes

¿Qué es PyTorch Monarch?

Es un runtime experimental de Meta que permite controlar un cluster completo de GPUs desde un solo programa Python, usando un modelo de actores y mallas de procesos en vez de código distribuido explícito por nodo.

¿Por qué era necesario portarlo a ROCm?

Porque el runtime original solo corría sobre CUDA. Portarlo a ROCm permite usarlo en clusters de GPU AMD Instinct, el hardware detrás de proyectos de entrenamiento a gran escala como el cluster MI325 de AMD.

¿Qué significa single-controller en este contexto?

Que un único programa Python, corriendo en un proceso controlador, orquesta la ejecución en todos los nodos del cluster, en vez de que cada nodo corra su propia copia del script de entrenamiento de forma independiente.

¿Monarch reemplaza a NCCL o RCCL?

No. Monarch se apoya en ellas: en GPUs NVIDIA usa NCCL, en GPUs AMD usa RCCL. Monarch es la capa de orquestación y tolerancia a fallos por encima de esas librerías de comunicación colectiva.

¿Se puede usar Monarch fuera de Meta hoy?

El código está disponible como proyecto abierto y se puede compilar desde el código fuente, pero AMD y Meta lo describen como un runtime en desarrollo activo, no como un producto estable de uso general todavía.

¿Qué diferencia hay entre un checkpoint tradicional y la recuperación de Monarch?

El checkpoint tradicional reinicia todo el trabajo desde el último punto guardado cuando falla un nodo. Monarch aísla el fallo en el actor afectado y deja que el resto del cluster siga entrenando mientras ese nodo se recupera.

Referencias

📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.

Imagen destacada: Foto de Caspar Camille Rubin en Unsplash


Javier Alarcón

Ingeniero de infraestructura especializado en redes, sistemas Linux, Kubernetes y arquitecturas cloud. Cubre hardware, networking, observabilidad y prácticas de ingeniería para equipos de producción.

0 Comentarios

Deja un comentario

Marcador de posición del avatar

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.