La computación de alto rendimiento (HPC) y las cargas de trabajo de IA/ML modernas enfrentan desafíos crecientes debido a la complejidad de las arquitecturas de hardware, la heterogeneidad de los sistemas (CPUs, GPUs, aceleradores) y la necesidad de una gestión eficiente de la concurrencia y la sincronización a escala distribuida. Los modelos de programación tradicionales a menudo luchan por explotar de manera óptima estas arquitecturas, lo que lleva a subutilización de recursos y latencias elevadas.

CARTS aborda este problema fundamental de la computación distribuida al introducir un modelo de ejecución event-driven que descompone las aplicaciones en unidades de trabajo finas e independientes, denominadas Event-Driven Tasks (EDTs), y gestiona explícitamente las dependencias de datos a través de DataBlocks y Events. Esta aproximación permite una programación dinámica y una optimización a nivel de compilador que se adapta mejor a las características de los sistemas distribuidos y heterogéneos, superando las limitaciones de los enfoques estáticos o basados en barreras globales.

Históricamente, la idea de descomponer el trabajo en unidades pequeñas con dependencias explícitas se remonta a modelos como el 'dataflow programming' y los 'codelets', que buscan maximizar el paralelismo y la localidad de datos. CARTS revitaliza estos principios aplicándolos en el contexto de un pipeline de compilación moderno basado en MLIR y LLVM, permitiendo optimizaciones profundas que serían difíciles de lograr con runtimes o compiladores monolíticos.

Arquitectura del Sistema

CARTS se construye sobre el Abstract Runtime System (ARTS), que implementa el modelo de 'codelets' para la ejecución de tareas finas y event-driven en sistemas distribuidos. Los componentes clave de ARTS incluyen:

- Event-Driven Tasks (EDTs): Unidades atómicas de trabajo que se ejecutan una vez que todas sus dependencias de datos están satisfechas. Son el equivalente a los 'codelets'.
- DataBlocks: Regiones de memoria que contienen los datos necesarios para las tareas. ARTS rastrea la ubicación de estos DataBlocks en nodos distribuidos para asegurar un acceso eficiente.
- Events: Señales que indican la disponibilidad de un DataBlock o la finalización de una tarea, facilitando la sincronización sin bloqueos pesados.
- Epochs: Límites de sincronización que agrupan tareas, asegurando que todas las tareas dentro de un grupo se completen antes de avanzar a la siguiente fase.

El pipeline del compilador CARTS comienza con la traducción de código C/OpenMP a MLIR utilizando Clang/Polygeist. Esta conversión maneja múltiples dialectos de MLIR (OpenMP, SCF, Affine, Arith). Posteriormente, un dialecto ARTS personalizado en MLIR transforma las tareas de OpenMP de alto nivel en EDTs, DataBlocks, Events y Epochs, lo que simplifica el análisis y la optimización. Se aplican pases de optimización para EDTs (ej. eliminación de tareas redundantes), gestión de DataBlocks (análisis de patrones de acceso a memoria) y manejo de Events (asignación y gestión), junto con optimizaciones clásicas como 'dead code elimination' y 'common subexpression elimination'. Finalmente, el MLIR optimizado se convierte a LLVM IR, donde las regiones EDT se delinean en funciones y se insertan llamadas a la API de ARTS para la gestión de tareas, DataBlocks, epochs y events. El binario resultante se ejecuta sobre el runtime de ARTS, que programa dinámicamente las tareas basándose en la disponibilidad de datos.

Pipeline de Compilación CARTS

  1. 1 C/OpenMP Source Código fuente de la aplicación HPC.
  2. 2 Clang/Polygeist Traduce C/OpenMP a MLIR, manejando dialectos como OpenMP, SCF, Affine.
  3. 3 MLIR (Dialectos Base) Representación intermedia con dialectos estándar.
  4. 4 ARTS Dialect Conversion Transforma tareas OpenMP en EDTs, DataBlocks, Events, Epochs.
  5. 5 MLIR (ARTS Dialect) Representación intermedia específica de ARTS para análisis y optimización.
  6. 6 Optimization Passes Optimización de EDTs, gestión de DataBlocks, manejo de Events, DCE, CSE.
  7. 7 Lowering to LLVM IR Convierte MLIR a LLVM IR, insertando llamadas a la API de ARTS.
  8. 8 ARTS Runtime Ejecuta el binario, programando dinámicamente tareas basadas en datos.
CapaTecnologíaJustificación
compute MLIR Framework de representación intermedia extensible para el compilador, permitiendo dialectos específicos de dominio para ARTS.
compute LLVM Backend de compilación para la generación de código máquina optimizado y la integración con el runtime ARTS.
compute Clang/Polygeist Frontend para la traducción de código C/OpenMP a MLIR, sirviendo como punto de entrada al pipeline de compilación.
orchestration ARTS Runtime Sistema de ejecución distribuido que programa dinámicamente Event-Driven Tasks (EDTs) basándose en la disponibilidad de DataBlocks y Events.

Fundamentos Teóricos

El modelo de 'codelets' que inspira ARTS tiene sus raíces en la investigación de sistemas de ejecución paralela y 'dataflow' de las últimas décadas. Conceptos similares se encuentran en trabajos como el modelo de 'dataflow graphs' propuesto por Dennis en los años 70, que visualizaba la computación como un flujo de datos a través de nodos de operación. La idea de tareas finas y la gestión explícita de dependencias de datos es un pilar en la investigación de la computación paralela y distribuida.

La utilización de MLIR (Multi-Level Intermediate Representation) como base para el compilador CARTS se alinea con la tendencia moderna en la investigación de compiladores de utilizar representaciones intermedias flexibles y extensibles. MLIR, desarrollado por Google, permite definir dialectos específicos de dominio, lo que facilita la implementación de optimizaciones y transformaciones a diferentes niveles de abstracción, desde el código fuente de alto nivel hasta el LLVM IR de bajo nivel. Esto es crucial para manejar la complejidad de las arquitecturas heterogéneas y las optimizaciones específicas de HPC que CARTS busca lograr.