Paralelismo y orquestación en IA

Rubén Rodríguez Abril

El paralelismo y la orquestación son esenciales en IA debido al crecimiento exponencial de modelos como GPT y DeepSeek, que requieren miles de chips y meses de entrenamiento. Se llama paralelismo a la ejecución de varios procesos simultáneamente en múltiples procesadores. La orquestación es la coordinación de las numerosas piezas físicas y lógicas que integran un centro de computación, a través de herramientas como Kubernetes, Ray y Slurm. Slurm destaca por su simplicidad en proyectos pequeños, mientras que Kubernetes y Ray son ideales para escalabilidad y complejidad.

Introducción

A medida que los modelos de lenguaje y en general los sistemas de aprendizaje profundo han aumentado su número de parámetros, también lo ha hecho la cantidad de poder computacional necesaria para su entrenamiento.

Así, AlexNet, la primera red clasificadora de carácter general, fue entrenada en tan sólo dos GPUs durante un periodo de 5 a 6 días. En contraste, los modelos de GPT o DeepSeek más avanzados en la actualidad emplean miles de chips para su entrenamiento a lo largo de varios meses.

El entrenamiento de un modelo de Deep Learning, que antes podía llevarse a cabo en un simple ordenador personal, hoy se realiza en gigantescos centros de datos bastante caros en términos energéticos. Esta transformación requiere un extraordinario esfuerzo logístico que coordine las tareas de computación y almacenamiento de datos, así como de transferencia de los mismos entre las diferentes partes del sistema.

Paralelismo

Debido al enorme tamaño de los modelos de lenguaje, el paralelismo -es decir, la ejecución simultánea de varios procesos en paralelo (que deben coordinarse entre ellos)- se ha convertido en un elemento fundamental en la ejecución de modelos de aprendizaje profundo, tanto en ámbito de entrenamiento como de inferencia.

Se distinguen cuatro niveles principales de paralelismo en este ámbito:

Paralelismo de datos: La carga de datos se reparte entre diferentes GPUs.

Paralelismo de tensores: La multiplicación de una matriz demasiado grande se fracciona y distribuye entre diferentes GPUs.

Paralelismo de procedimiento: Las capas del modelo se asignan a GPUs específicas.

Mezcla de expertos: Varias subredes funcionan paralelamente en diferentes partes del modelo.

Estas categorías no son excluyentes y a menudo se combinan entre sí, dando lugar a arquitecturas híbridas.

Paralelismo de datos

Los datos de entrenamiento, ya consistan en imágenes, cadenas de texto o audio, se integran en lotes de tamaño fijo, que son distribuidos entre las diferentes GPUs. Cada unidad de procesamiento trabaja de un modo independiente, pero al final de cada iteración, las GPUs intercambian gradientes (proceso All-reduce) con el objetivo de actualizar homogéneamente los parámetros del modelo.

Paralelismo de procedimiento (o pipeline)

Cada capa de un modelo Deep Learning es asignado a una o varias GPUs. Los datos de salida de cada GPU son transferidos a las GPUs encargadas de procesar las operaciones capa siguiente.

Paralelismo de tensores

A menudo, las capas de los modelos de aprendizaje profundo son demasiado grandes como para ser gestionados por una sóla GPU, particularmente cuando se trata de unidades de atención o capas densamente conectadas (p.e. embedding). En estos casos, una única multiplicación matricial es realizada por varios procesadores, que se encargan de calcular su correspondiente fragmento en la matriz de resultado. Cada GPU sólo debe almacenar en este caso una fracción de los pesos de la capa. Los resultados (y no sólo los gradientes) de un procesador son transmitidos al resto a través de un proceso denominado All-to-All.

Mezcla de expertos (MoE)

En el sistema Mezcla de Expertos (MoE), diferentes subredes denominadas expertos operan en paralelo dentro de un mismo modelo. Un mecanismo enrutador, se encarga de distribuir la información a cada uno de los expertos. La información es combinada y ponderada por una puerta, que es la encargada de generar una salida unitaria.

En los mecanismos de atención, a menudo la red orientada hacia adelante es sustituida por una mezcla de expertos.

Por lo general, se asumía que cada subred se especializaba en procesar un determinado tipo de información (razonamiento general, generación de código, etc…). Sin embargo, estudios recientes demuestran que diferentes expertos se alternan dentro de una misma cadena de texto. Así que probablemente la eficiencia de este sistema deriva del hecho de que sólo una parte de la red es activada a cada momento, y que por lo tanto la mezcla de expertos representa una aplicación del principio de esparsión (sparsity) dentro de una red neuronal.

Orquestación en IA

Llámase orquestación al conjunto de técnicas que permiten la coordinación y jerarquización de diferentes sistemas computacionales y de software.

Debido a la enorme cantidad de componentes físicos existentes y la complejidad de los flujos de información, los centros de datos se articulan en una arquitectura estratificada donde se pueden distinguir diversos niveles, tanto en el plano puramente físico (hardware) como en el plano lógico.

En esta sección analizaremos los tres grandes sistemas de orquestación utilizados en el ámbito del Procesamiento del Lenguaje Natural: Kubernetes, Ray y Slurm.

Kubernetes

Kubernetes es un software de gestión de clústeres de servidores lanzado por Google en el año 2014, y que hoy en día tiene una amplia aplicación en el ámbito de la computación distribuida.

Los nodos de Kubernetes

La unidad básica de Kubernetes es el nodo, que es una máquina virtual o física en la que corre una instancia del kernel del sistema operativo. Dentro de cada nodo se despliegan unidades aisladas de ejecución, denominadas contenedores, que se encargan de la ejecución de una carga de trabajo (workload). Estos contenedores se agrupan en pods, que comparten una misma configuración y una base de datos.

Así, pues, la estructura jerárquica del nodo es como sigue:

Nodo. Es una máquina que puede ser virtual (VM Kubernetes) o física (bare metal Kubernetes). A cada nodo se le asignan procesadores (CPUs, GPUs, TPUs, etc.) y otros recursos como memoria RAM, almacenamiento persistente (discos duros locales, SSDs), infraestructura de red (Ethernet, InfiniBand, etc..) o dispositivos de entrada y salida (USB, tarjetas de red…). El nodo es controlado por un gestor denominado kubelet.

Pod. Es la unidad mínima de orquestación. A cada pod se le asignan, en el mismo momento de su creación, recursos dentro del nodo, así como una dirección IP dentro de la red de área local del clúster. En el ámbito de un modelo de lenguaje distintos pods pueden encargarse de procesos específicos como preprocesamiento, entrenamiento, motor de inferencia, almacenamiento (guarda los checkpoints del modelo en la memoria), postprocesamiento, comunicación con usuarios (API Gateway) y monitoreo.

Contenedor. Es una unidad aislada de ejecución que contiene una aplicación en marcha así como sus bibliotecas y dependencias. A modo de ejemplo, en el pod del motor de inferencia se crea un contenedor por cada instancia del modelo de lenguaje, lo que permite gestionar diversas consultas de usuario paralelamente. Si el sistema es pequeño (bajo tráfico) es recomendable crear contenedores para servicios secundarios como APIs de usuario o posprocesamiento de datos, en lugar de asignarlos a pods separados. No es posible crear contenedores aisladamente, sino que deben estar integrados dentro de un pod. Todos ellos corren en el marco de un entorno de ejecución específico (container runtime).

Desde el punto de vista procedimental, la ejecución de un sistema en Kubernetes debe seguir los siguientes pasos:

-en primer lugar deben crearse las imágenes de los contenedores (es decir, se fija su directorio de trabajo y se descargan las bibliotecas y dependencias necesarias) mediante un archivo específico denominado Dockerfile.

-tras ello, se procede al lanzamiento del pod. Un archivo YAML describe las características de este último (sus metadatos) e indica cuáles son las imágenes de sus contenedores. El comando kubectl apply de Kubernetes se encarga de ponerlo en marcha dentro del clúster.

El plano de control

Este nivel es el encargado de coordinar todos los nodos de un centro de datos. En Kubernetes. El plano de control está integrado por los siguientes componentes:

-Un planificador general (scheduler), que distribuye las cargas de trabajo entre los nodos.

-Un API Server, encargado de procesar peticiones con formato JSON sobre HTTP.

-La base de datos de configuración etcd, que almacena el estado global del clúster.

-Un gestor de controladores (controller manager), que regulan el comportamiento de pods y contenedores.

A nivel de componentes de red, cada vez que un usuario quiere inicializar un pod envía las peticiones descritas en el apartado anterior al clúster a través del API Server. Éste registra la petición en etcd y la envía a su vez al planificador. El planificador elige el nodo de Kubernetes en el que estén disponibles recursos suficientes. La unidad kubelet del nodo elegido inicializa dentro del nodo un nuevo pod y nuevos contenedores.

Figura 1. En verde, el plano de control de Kubernetes. En azul, sus nodos, controlados por un Kubelet y en los que corren varios pods. El API Server sirve como interfaz de comunicación del Sheduler y el gestor de controladores con los nodos y con el operador humano del clúster. Fuente: Wikipedia.

Ray

Ray es un motor de computación distribuida, desarrollado por la Universidad de Berkeley y su laboratorio de investigación BAIR, cuyo fin principal es permitir el escalado de aplicaciones de IA, posibilitando que el código de estas últimas, aunque haya sido diseñado para funcionar en un simple ordenador portátil, pueda con facilidad ser ejecutado en centros de datos o incluso en Kubernetes, sin demasiadas modificaciones. Ray paraleliza automáticamente (sin que intervenga el programador) los algoritmos de aprendizaje de máquina y distribuye los recursos computacionales (CPUs, GPUs, etc.) entre todos los hilos.

La plataforma se articula en un doble nivel:

-El núcleo (Ray Core) es la verdadera base del sistema, ejecuta tareas (Tasks) paralelamente, almacena objetos persistentes (Actors) como los datos de las sesiones de usuario, que tienen que guardarse entre ejecución y ejecución, y gestiona el almacenamiento de datos (Object Store).

-Las bibliotecas de Ray (Ray Libraries) ofrecen código para datos (Data), entrenamiento (Train), ajuste de los hiperparámetros del modelo (Tune), aprendizaje reforzado (RLib) y servidores (Serve).

Figura 2: Esquema general del motor de computación Ray, que muestra el núcleo y las bibliotecas. Fuente: Página en GitHub del proyecto Ray.

Slurm

Slurm (Simple Linux Utility of Resource Management) es un proyecto de código abierto (licencia GPL) desarrollado inicialmente por el Lawrence Livermore National Laboratory (LLNL) para contribuir a la coordinación de clústeres, la optimización de recursos dentro de los mismos y el balanceo de las cargas de trabajo em entornos de alto rendimiento (HPC). En la actualidad, Slurm es utilizado en el entrenamiento y la inferencia de buena parte de los modelos de lenguaje más avanzados existentes en la actualidad, entre los que podemos citar a las series GPT, Mistral, DeepSeek y Llama.

A primera vista, el funcionamiento de la plataforma es bastante sencillo. Se basa fundamentalmente en scripts y en órdenes del usuario impartidas a través de la línea de comando. Los scripts son archivos de procesamiento por lotes, ejecutados en Bash. En ellos, mediante directivas se fija el nombre de la tarea, se definen de los archivos logs, se asignan procesadores y memoria para la ejecución de la tarea y además se puede establecer un tiempo máximo de ejecución. Seguidamente, se ejecutan las instrucciones contenidas en el mismo, cargándose los módulos y ejecutándose el archivo Python que contiene el modelo de lenguaje o cualquier otra tarea asignada.

Entre los comandos de línea más utilizados se encuentran sbatch (que envía a los scripts a la cola de trabajo, ejecutándolos en segundo plano), srun (que ejecuta una tarea en primer plano, de un modo interactivo, bloqueando la terminal), squeue (que sirve para inspeccionar la cola de trabajo) o cat (que se usa para consultar los blogs).

Slurm, por su ligereza, es ideal para pequeños proyectos que sólo involucren unas pocas docenas de CPUs y procesos de ejecución paralelos. En estas escalas, el sistema de orquestación de Kubernetes es innecesariamente complejo, ya que requiera crear un archivo YAML para el pod, crear imágenes para los contenedores, y por último lanzar el pod, entre otras tareas. En Slurm, basta con un archivo por lotes para asignar los recursos (procesadores y memoria) a la tarea y comenzar la ejecución de la misma.

Esta simplicidad hace que Slurm sea ideal para aquellos investigadores, profesionales o amateurs, que quieran crear su propio proyecto personal.

SERIES

LLMs

RAG