El crecimiento exponencial de las capacidades de los modelos de IA y los tamaños de los datasets ha expuesto limitaciones críticas en las arquitecturas de almacenamiento tradicionales. Mientras el rendimiento computacional de las GPU se triplica cada dos años, el almacenamiento y la interconexión no han mantenido el mismo ritmo, creando cuellos de botella que impactan directamente la utilización de las GPU y el tiempo de comercialización. Este problema fundamental de la computación distribuida, donde la velocidad de un componente (computación) supera drásticamente la de otro (almacenamiento), se agrava con la distribución geográfica de las GPU y los datasets masivos, lo que ralentiza la velocidad de iteración en la investigación de IA. La tesis central es que una arquitectura de almacenamiento optimizada para las características de E/S de la IA —alto throughput sostenido, latencias pMax predecibles y patrones de E/S variables— es indispensable para desbloquear el potencial completo de la computación de IA.
Históricamente, las arquitecturas de almacenamiento de objetos se diseñaron para cargas de trabajo web con requisitos de latencia más modestos y optimizadas para el costo por byte en HDDs. Sin embargo, las cargas de trabajo de IA exigen acceso a datos en milisegundos desde flash y una alta disponibilidad, pero no necesariamente la replicación global por defecto. La necesidad de maximizar la utilización de GPU y la velocidad de investigación ha obligado a Meta a reevaluar los tradeoffs fundamentales de su BLOB storage, pasando de una arquitectura centrada en la durabilidad y disponibilidad global a una optimizada para el rendimiento regional y la eficiencia energética, con un enfoque en la reducción de la latencia de cola y la gestión de hotspots.
Arquitectura del Sistema
La arquitectura de BLOB storage de Meta se construye sobre Tectonic, una capa de bloques regional y multi-tenant que proporciona alta durabilidad y disponibilidad mediante erasure coding, y soporta tiering de medios (HDD y flash). Sobre Tectonic, las capas de BLOB storage exponen una "fabric" de almacenamiento globalmente escalable. La evolución de la arquitectura se centró en dos áreas clave: maximizar la utilización de GPU y maximizar la velocidad de investigación.
Para maximizar la utilización de GPU, se realizaron cambios fundamentales. Primero, se unificó el esquema de metadatos, consolidando la información dispersa en múltiples capas (namelayer, volumeslayer, containerlayer) en un único esquema plano respaldado por ZippyDB. Esto transformó las búsquedas de metadatos de O(N) a O(1), resolviendo rutas a direcciones de almacenamiento de manera mucho más eficiente. Segundo, se eliminó el proxy de datos en el dataplane, reemplazándolo por un SDK de cliente "fat" capaz de transmitir bytes directamente desde los servidores de almacenamiento Tectonic a los clientes, mejorando la eficiencia energética y reduciendo la latencia y aumentando el throughput. Tercero, se adoptó un despliegue regional del stack de BLOB storage, co-localizado con las GPU en cada región de IA, lo que reduce la latencia de red y elimina la replicación global por defecto.
Para manejar picos de tráfico y hotspots, se implementaron dos mecanismos: una caché de datos distribuida que aprovecha la memoria spare en los hosts de GPU (reutilizando componentes del subsistema Owl de Meta) y una caché de metadatos de "readplan" distribuida (similar a memcache) para mapeos de ruta a dirección de almacenamiento. Estas cachés absorben picos, reducen los requisitos de E/S y mejoran las latencias p50 y p99. Además, se aplicaron optimizaciones de protocolo, como "hedged reads" en el cliente para mitigar el impacto de nodos lentos (laggards) y un control de concurrencia dinámico en el SDK del cliente para ajustar el paralelismo basado en señales de congestión a nivel de aplicación, evitando picos de egreso durante eventos de checkpointing.
Para maximizar la velocidad de investigación, se introdujo una arquitectura de caché jerárquica multinivel. El BLOB storage global respaldado por HDDs actúa como fuente de verdad. La memoria y el flash en el host de GPU funcionan como cachés L1 y L2, respectivamente. La "fabric" de BLOB storage regional respaldada por flash actúa como caché L3. El SDK de BLOB storage expone una API prefetch() explícita que permite a los dataloaders precargar datos necesarios en segundo plano, hidratando datos desde el almacenamiento remoto a la caché L3 regional y precalentando la caché de metadatos. Se implementan políticas de desalojo automáticas (TTL, LRU) y conscientes de la capacidad/cuota para gestionar el ciclo de vida de los datos en la caché L3.
Flujo de Lectura de Datos en BLOB Storage (Arquitectura Antigua)
- 1 Cliente Solicita getObject("/bucket/path")
- 2 API Server Recibe la solicitud
- 3 Namelayer Búsqueda de metadatos (puede cruzar regiones)
- 4 Volumeslayer Búsqueda de metadatos
- 5 Containerlayer Búsqueda de metadatos, resuelve a (blockId, offset, size)
- 6 API Server Proxies datos desde Tectonic
- 7 Tectonic Layer Sirve los bloques de datos
- 8 Cliente Recibe los datos
Flujo de Lectura de Datos en BLOB Storage (Arquitectura Nueva)
- 1 Cliente SDK Solicita getObject("/bucket/path")
- 2 Cliente SDK Emite getReadPlan("/bucket/path") al API Server
- 3 API Server Búsqueda O(1) en el nuevo Metadata Store (ZippyDB)
- 4 API Server Devuelve ReadPlanResult (blockId, offset, size) al SDK
- 5 Cliente SDK (Tectonic BlockClient) Stream de datos directo desde Tectonic
- 6 Tectonic Layer Sirve los bloques de datos
- 7 Cliente SDK Recibe los datos
| Capa | Tecnología | Justificación |
|---|---|---|
| storage | Tectonic | Capa fundamental de bloques de almacenamiento regional, multi-tenant, con alta durabilidad y disponibilidad mediante erasure coding y tiering de medios. |
| storage | BLOB Storage (capa superior) | Proporciona una "fabric" de almacenamiento globalmente escalable, exponiendo APIs de objeto, sistemas de archivos y dispositivos de bloque sobre Tectonic. Despliegue regional co-localizado con GPUs. |
| storage | ZippyDB | Backend para el subsistema de metadatos unificado, permitiendo búsquedas O(1) para resolver rutas a direcciones de almacenamiento. |
| cache | Distributed Data Cache (basado en Owl) | Aprovecha la memoria spare en hosts de GPU para cachear datos frecuentemente accedidos, absorbiendo picos y reduciendo requisitos de E/S. Integrado directamente en el BLOB-storage client SDK. |
| cache | Readplan Metadata Cache (similar a memcache) | Caché distribuida en memoria para mapeos de ruta a dirección de almacenamiento (readplans), mejorando la latencia de acceso a metadatos. |
| compute | GPU | Unidades de procesamiento primarias para cargas de trabajo de IA, cuyo rendimiento es el objetivo principal de optimización del almacenamiento. Despliegue geo-distribuido. |
Trade-offs
Ganancias
- ▲ Utilización de GPU
- ▲▲ Velocidad de Iteración en Investigación de IA
- ▲ Latencia de Acceso a Datos (pMax)
- ▲ Eficiencia Energética del Almacenamiento
Costes
- △ Complejidad del Cliente (Fat Client SDK)
- △ Durabilidad/Disponibilidad Global por Defecto
Fundamentos Teóricos
El problema de la disparidad de rendimiento entre la computación y el almacenamiento, y la necesidad de arquitecturas de almacenamiento que se adapten a las características de las cargas de trabajo, ha sido un tema recurrente en la investigación de sistemas distribuidos y bases de datos. El concepto de una jerarquía de memoria y almacenamiento, con diferentes niveles de latencia, throughput y costo, es un principio fundamental de la arquitectura de computadoras, formalizado por papers como "A Case for Redundant Arrays of Inexpensive Disks (RAID)" de Patterson, Gibson y Katz (1988), que abordó la fiabilidad y el rendimiento del almacenamiento. La idea de usar cachés multinivel para ocultar la latencia de acceso a datos remotos o lentos es una aplicación directa de los principios de localidad temporal y espacial, ampliamente estudiados en la gestión de memoria de sistemas operativos y arquitecturas de CPU.
La optimización de la latencia de cola (tail latency) y la mitigación de "laggards" a través de técnicas como "hedged reads" se basa en principios de redundancia y paralelismo que se encuentran en algoritmos de tolerancia a fallos y sistemas distribuidos. Trabajos sobre la gestión de recursos y la programación en sistemas distribuidos, como los relacionados con la teoría de colas y la optimización de latencia en datacenters, han explorado cómo el rendimiento de un sistema puede ser dominado por el percentil más alto de latencias. La consolidación de metadatos y la eliminación de proxies de datos reflejan un principio de diseño de sistemas de "end-to-end argument" (Saltzer, Reed, Clark, 1984), que sugiere que ciertas funciones son mejor implementadas en los extremos de un sistema para evitar sobrecarga y complejidad innecesarias en las capas intermedias, especialmente cuando los requisitos de rendimiento son estrictos.