Articulo de referencia

Procesamiento de flujos

En informática , el procesamiento de flujos (también conocido como procesamiento de flujos de eventos , procesamiento de flujos de datos o procesamiento de flujos distribuidos )...

En informática , el procesamiento de flujos (también conocido como procesamiento de flujos de eventos , procesamiento de flujos de datos o procesamiento de flujos distribuidos ) es un paradigma de programación que considera los flujos , o secuencias de eventos en el tiempo, como los objetos centrales de entrada y salida de la computación . El procesamiento de flujos abarca la programación de flujo de datos , la programación reactiva y el procesamiento de datos distribuidos . [ 1 ] Los sistemas de procesamiento de flujos utilizan algoritmos de flujo para rastrear el procesamiento paralelo de flujos de datos. La pila de software para estos sistemas incluye componentes como modelos de programación y lenguajes de consulta , para expresar la computación; sistemas de gestión de flujos para la distribución y la planificación ; y componentes de hardware para la aceleración , incluyendo unidades de punto flotante , unidades de procesamiento gráfico y matrices de puertas programables en campo . [ 2 ]

El paradigma de procesamiento de flujos simplifica el software y el hardware paralelos al restringir los tipos de computación paralela que se pueden realizar. Dada una secuencia de datos ( un flujo ), se aplica una serie de operaciones ( funciones kernel ) a cada elemento del flujo. Las funciones kernel suelen estar segmentadas , y se intenta una reutilización eficiente de la memoria local en el chip para minimizar la pérdida de ancho de banda asociada con la interacción con la memoria externa. El flujo uniforme , en el que se aplica una única función kernel a todos los elementos del flujo, es típico. Dado que las abstracciones kernel y de flujo exponen las dependencias de datos, las herramientas del compilador pueden automatizar y optimizar completamente las tareas de gestión en el chip. El hardware de procesamiento de flujos puede utilizar técnicas como el scoreboarding para iniciar el acceso directo a memoria (DMA) cuando se resuelven las dependencias. La eliminación de la gestión manual de DMA reduce la complejidad del software, mientras que la menor dependencia de la E/S en caché de hardware disminuye el consumo de memoria requerido por unidades computacionales especializadas, como las unidades aritmético-lógicas .

Durante la década de 1980 se exploró el procesamiento de flujos dentro de la programación de flujo de datos . Un ejemplo es el lenguaje SISAL .

Aplicaciones

El procesamiento de flujos de datos puede considerarse una solución de compromiso, basada en un modelo centrado en los datos que funciona bien para aplicaciones tradicionales de DSP o GPU (como el procesamiento de imágenes, vídeo y señales digitales ), pero no tan bien para el procesamiento de propósito general con acceso a datos más aleatorio (como las bases de datos). Al sacrificar cierta flexibilidad en el modelo, este enfoque puede permitir una ejecución más sencilla, rápida y eficiente. Dependiendo del contexto, el diseño del procesador puede ajustarse para lograr la máxima eficiencia o un compromiso con la flexibilidad. [ 3 ]

El procesamiento de flujos de datos es especialmente adecuado para aplicaciones que presentan tres características:

  • Intensidad de cómputo , definida como el número de operaciones aritméticas por cada operación de entrada/salida o referencia a la memoria global. En muchas aplicaciones de procesamiento de señales, esta relación supera ampliamente la proporción 50:1 y sigue aumentando con la complejidad algorítmica.
  • El paralelismo de datos , que existe en un núcleo cuando se aplica la misma función a todos los registros de un flujo de entrada, permite procesar varios registros simultáneamente sin esperar los resultados de los registros anteriores.
  • La localidad de datos , una forma de localidad temporal común en las aplicaciones de procesamiento de señales y medios, se caracteriza por generar datos una sola vez, leerlos una o dos veces más tarde en la aplicación y no volver a utilizarse. Los flujos intermedios que se transmiten entre núcleos, así como los datos intermedios dentro de las funciones del núcleo, pueden capturar esta localidad directamente en el modelo de programación de procesamiento de flujos.

Algunos ejemplos de registros dentro de flujos incluyen:

  • En gráficos, cada registro puede constar de información sobre el vértice, la normal y el color de un triángulo.
  • En el procesamiento de imágenes, cada registro puede ser un solo píxel de una imagen.
  • En un codificador de vídeo, cada registro puede tener 256 píxeles, formando un macrobloque de datos.
  • En el procesamiento de señales inalámbricas, cada registro podría ser una secuencia de muestras recibidas de una antena.

Para cada registro, el procesamiento generalmente se limita a leer la entrada, realizar operaciones con los datos y escribir el resultado en la salida. Es posible tener múltiples entradas y salidas, pero la memoria no se lee ni se escribe dentro de la misma aplicación. [ 4 ]

Ejemplos de código

A modo de ilustración, los siguientes fragmentos de código demuestran la detección de patrones dentro de flujos de eventos. El primer ejemplo muestra el procesamiento de un flujo de datos mediante una consulta SQL continua : una consulta continua que procesa los datos entrantes en función de las marcas de tiempo y la duración de la ventana. Este fragmento de código ilustra una JOIN de dos flujos de datos: uno que representa la acción ordersy el otro que representa la acción resultante trades. [ 5 ] La consulta genera un flujo de todas las órdenes coincidentes con una operación dentro de un segundo después de que se haya colocado la orden. El flujo de salida está ordenado por marca de tiempo; en este caso, la marca de tiempo se origina en el ordersflujo.

SELECT DataStream Orders . TimeStamp , Orders . orderId , Orders . ticker , Orders . amount , Trade . amount FROM Orders JOIN Trades OVER ( RANGE INTERVAL '1' SECOND FOLLOWING ) ON Orders . orderId = Trades . orderId ;

Otro fragmento de código de ejemplo detecta bodas dentro de una secuencia de eventos externos, como el repique de campanas de iglesia, la aparición de un hombre con esmoquin o traje de mañana, una mujer con un vestido blanco y el lanzamiento de arroz. Un evento "complejo" o "compuesto" es el evento de alto nivel inferido a partir de estos eventos constituyentes: en este caso, que se está celebrando una boda. [ 6 ]

CUANDO Person.Gender ES IGUAL A "hombre" Y Person.Clothes ES IGUAL A "esmoquin" SEGUIDO POR Persona.Ropa ES IGUAL A "bata" Y (Campana de iglesia O Arroz volador) EN 2 horas Boda ACCIÓN 

Comparación con paradigmas paralelos anteriores

Las primeras computadoras se basaban en un paradigma de ejecución secuencial. Las CPU tradicionales utilizan una arquitectura de instrucción única, dato único (SISD) , lo que significa que conceptualmente realizan una operación a la vez. [ 7 ] A medida que aumentaban las demandas de computación, el volumen de datos a procesar creció rápidamente, lo que puso de manifiesto las limitaciones de los modelos de programación secuencial. Se exploraron diversos enfoques para permitir la computación a gran escala, principalmente mediante la explotación de la ejecución paralela.

Una de las principales consecuencias de estos esfuerzos fue la arquitectura SIMD (Instrucción Única, Datos Múltiples) , que permite que una sola instrucción opere simultáneamente sobre múltiples elementos de datos. En microprocesadores de propósito general, SIMD se implementa frecuentemente mediante SWAR (Instrucción Única dentro de un Registro) . Al incorporar estructuras de ejecución distintas para flujos de instrucciones separados, también se puede lograr el paralelismo MIMD (Instrucción Múltiple, Datos Múltiples) . [ 7 ] [ 8 ]

Aunque estos paradigmas son efectivos, las implementaciones de hardware físico se enfrentan a estrictas limitaciones, como los requisitos de alineación de memoria, la sobrecarga de sincronización y la escalabilidad limitada. En consecuencia, relativamente pocos procesadores SIMD sobrevivieron como componentes independientes; la mayoría se han integrado en CPU de propósito general. [ 8 ] [ 9 ]

Un ejemplo fundamental de estos paradigmas es un programa que suma dos matrices, cada una con 100 vectores de cuatro componentes (lo que da un total de 400 valores numéricos).

Paradigma convencional y secuencial

En el paradigma secuencial estándar, la operación se ejecuta de forma iterativa utilizando un único bucle:

for ( int i = 0 ; i < 400 ; i ++ ) { result [ i ] = source0 [ i ] + source1 [ i ]; }

Si bien existen variaciones estructurales, como el uso de bucles internos anidados o diseños de datos basados ​​en matrices de estructuras, el cálculo subyacente se basa fundamentalmente en este modelo de ejecución lineal.

Paradigma SIMD paralelo, registros empaquetados (SWAR)

// para cada vector for ( int elem = 0 ; elem < 100 ; elem ++ ) { vectorSum ( result [ elem ], source0 [ elem ], source1 [ elem ]); }

Este modelo ilustra de forma abstracta el paradigma asumiendo una vector_suminstrucción genérica. Si bien esta abstracción refleja cómo funcionan las instrucciones intrínsecas en la práctica, omite detalles de la implementación del hardware subyacente, como formatos de datos explícitos y anchos de bits de los componentes, para mayor claridad.

Al operar con estructuras de datos empaquetadas, este método reduce la cantidad de instrucciones aritméticas individuales necesarias para procesar los componentes del array. El control de bucles y la sobrecarga de saltos también se reducen debido al menor número de iteraciones. Estas mejoras en la eficiencia son el resultado directo de ejecutar múltiples operaciones aritméticas simultáneamente dentro de un único paso de ejecución de instrucciones. [ 10 ]

Sin embargo, debido a que un registro SIMD empaquetado tiene una capacidad de ancho de bits fija, la escalabilidad está inherentemente limitada por el tamaño máximo del registro. En este escenario, la aceleración por hardware está limitada por el ancho del vector de cuatro operaciones paralelas, una configuración estándar en arquitecturas como AltiVec y Streaming SIMD Extensions (SSE) . [ 11 ]

Paradigma de flujo paralelo (SIMD/MIMD)

// Este es un lenguaje ficticio con fines demostrativos. elements = array streamElement ([ number , number ])[ 100 ] kernel = instance streamKernel ( "@arg0[@iter]" ) result = kernel . invoke ( elements )

En el paradigma de procesamiento de flujos, los datos se tratan como una secuencia continua e ilimitada de elementos, en lugar de un conjunto de datos estático. En vez de gestionar la iteración explícitamente, el programa define una secuencia de flujo de datos, lo que permite que el entorno de ejecución aplique automáticamente la función del núcleo de cálculo a medida que llegan nuevos elementos de datos. Si bien se suele utilizar una correspondencia uno a uno entre los datos de entrada y salida por simplicidad, no es un requisito arquitectónico inherente; los núcleos pueden realizar transformaciones complejas, ventanas de agregación o modificaciones con estado. [ 12 ]

Los compiladores optimizados para este paradigma pueden realizar transformaciones de código automatizadas extensas, como el desenrollado de bucles . Esta abstracción permite que el rendimiento se ajuste de forma transparente a la capacidad del hardware, lo que posibilita la utilización de cientos de unidades aritmético-lógicas (ALU). [ 13 ] [ 14 ] Minimizar los patrones de acceso a datos complejos e impredecibles garantiza que se pueda acceder a un mayor porcentaje de la capacidad máxima de ejecución del hardware.

Aunque el procesamiento de flujo comparte características con las arquitecturas SIMD y MIMD más amplias, los conceptos siguen siendo distintos. [ 12 ] Si bien el hardware SIMD suele ejecutar operaciones de forma segmentada o en flujo continuo, las características de rendimiento estándar de SIMD difieren; el modelo de procesamiento de flujo impone un flujo de datos estructurado y una gestión de memoria explícita que permite una eficiencia de ejecución significativamente mayor. [ 15 ]

Cuando se implementaban en arquitecturas de propósito general, como las CPU estándar, las abstracciones de procesamiento de flujos a menudo producían ganancias de rendimiento limitadas, y algunos estudios históricos señalaban una aceleración de ejecución de tan solo aproximadamente 1,5x. [ 16 ] En contraste, los primeros procesadores de flujos dedicados lograron aumentos de rendimiento superiores a 10x, principalmente debido a archivos de registro especializados gestionados por hardware y niveles más altos de unidades de ejecución paralela. [ 17 ]

A pesar de las variaciones en la flexibilidad entre los modelos de implementación, el hardware de procesamiento de flujos generalmente impone restricciones estrictas tanto en la complejidad del núcleo como en el tamaño de las dimensiones del flujo. Por ejemplo, el hardware de procesamiento gráfico de consumo históricamente carecía de soporte para aritmética de alta precisión, carecía de capacidades complejas de indirección de punteros e imponía límites estrictos en el número máximo de instrucciones. [ 18 ]

Investigación

Las primeras investigaciones en procesamiento de flujos surgieron a finales de la década de 1990 y principios de la de 2000, impulsadas por los esfuerzos para aumentar la intensidad aritmética en las arquitecturas de procesamiento de gráficos y la computación de alto rendimiento. Los proyectos académicos, especialmente en la Universidad de Stanford , fueron pioneros en las primeras arquitecturas de procesamiento de flujos y diseños de compiladores que resultaron fundamentales para el hardware moderno de procesamiento paralelo de datos. [ 3 ] [ 19 ] Simultáneamente, investigadores industriales, incluidos grupos de AT&T , exploraron procesadores optimizados para flujos con el fin de optimizar el procesamiento de señales y las cargas de trabajo de telecomunicaciones, a medida que las unidades de procesamiento gráfico ganaban rápidamente rendimiento y programabilidad. [ 1 ] [ 20 ]

Tras estos esfuerzos fundamentales, el paradigma pasó de hardware experimental especializado a ecosistemas de software convencionales, lo que dio como resultado el desarrollo de numerosos lenguajes y marcos de procesamiento de flujo dedicados. [ 12 ]

Consideraciones sobre programación y diseño de datos

Un desafío principal en la computación paralela es la complejidad de mapear algoritmos a arquitecturas de hardware manteniendo la velocidad de desarrollo de software y el rendimiento en tiempo de ejecución. El hardware de transmisión inicial, como el prototipo Stanford Imagine, mitigó esto al utilizar un modelo de programación de un solo hilo que abstraía la asignación de memoria, las dependencias de datos y la planificación del acceso directo a memoria (DMA) . [ 21 ] Esta división de tareas surgió de la investigación en el Instituto Tecnológico de Massachusetts (MIT) y la Universidad de Stanford, que demostró que los programadores humanos son altamente efectivos en la partición algorítmica de alto nivel, mientras que las herramientas de compilación automatizadas sobresalen en la optimización de rutinas complejas de asignación y planificación de memoria. [ 22 ] [ 23 ] En contraste, las arquitecturas multinúcleo asimétricas, como Cell Broadband Engine , transfieren la partición estructural, la sincronización de procesos y la sobrecarga del equilibrio de carga directamente al desarrollador de software. [ 24 ]

La disposición de la estructura de datos impacta significativamente la eficiencia de ejecución de los paradigmas paralelos, requiriendo típicamente una elección entre una matriz de estructuras (AoS) y una estructura de matrices (SoA) . En la ingeniería de software de propósito general, los desarrolladores convencionalmente representan entidades de datos en memoria —por ejemplo, la ubicación de una partícula en el espacio 3D, el color de una pelota y su tamaño— como se muestra a continuación: [ 25 ]

// Una partícula en un espacio tridimensional. struct Particle { double x ; double y ; double z ;// 8 bits por canal, digamos que solo nos interesa RGB unsigned byte color [ 3 ]; float size ; // ... y muchos otros atributos pueden seguir... };

Cuando existen múltiples entidades en secuencia, se asignan de extremo a extremo, formando una topología de matriz de estructuras (AoS) . Si un algoritmo procesa solo un atributo en todos los elementos, como modificar únicamente las coordenadas 3D, el motor de ejecución debe omitir los atributos no utilizados en la memoria. Dado que las líneas de caché convencionales acceden a la memoria en bloques contiguos, la carga de atributos innecesarios resulta en una utilización ineficiente de la caché y un desperdicio de ancho de banda de memoria . Además, las operaciones SIMD estándar requieren que los elementos de entrada sean contiguos y estén correctamente alineados en la memoria para llenar eficientemente los carriles vectoriales. [ 25 ]

Para optimizar la transmisión de datos y la ejecución vectorial, los atributos se pueden separar en bloques paralelos distintos mediante una estructura de matrices (SoA) . Una representación SoA aísla los campos idénticos en matrices individuales y contiguas, como se muestra a continuación:

struct Particle { double * x ; double * y ; double * z ;byte sin signo * colorRojo ; byte sin signo * colorAzul ; byte sin signo * colorVerde ;flotar * tamaño ; };

Si bien la estructura de arreglos (SoA) optimiza las rutas de datos uniformes, introduce desventajas arquitectónicas importantes. Si una rutina debe operar simultáneamente en múltiples atributos distintos de una sola entidad, estos atributos pueden residir muy separados en la memoria virtual , lo que provoca fallos de caché graves y una mayor sobrecarga en la traducción de direcciones. Además, garantizar que cada arreglo independiente cumpla con los límites de alineación de memoria del hardware puede requerir relleno de datos, lo que aumenta el consumo total de memoria. La gestión dinámica de la memoria también se vuelve muy compleja cuando se deben agregar o eliminar elementos, ya que las modificaciones requieren el desplazamiento síncrono de elementos a través de múltiples arreglos desconectados. [ 26 ]

Por el contrario, las arquitecturas de procesamiento de flujo dedicadas utilizan ampliamente abstracciones estructuradas para unificar estos diseños. En las canalizaciones de vértices de las unidades de procesamiento gráfico (GPU) contemporáneas, el hardware proporciona un número fijo de ranuras de atributos, estandarizándose históricamente en torno a 16 líneas de entrada. [ 27 ] La aplicación especifica el número de componentes y el formato del tipo de datos para cada flujo de entrada, aunque la compatibilidad del hardware suele estar restringida a tipos de datos numéricos primitivos. Estos atributos independientes están vinculados a un bloque de memoria cohesivo mediante un parámetro de paso explícito. Al ajustar el paso de bytes entre elementos consecutivos de la matriz, los desarrolladores pueden formatear el flujo de datos como matrices intercaladas de estructuras (AoS) o estructuras separadas de matrices (SoA). En la etapa de ejecución, el hardware de la GPU reúne automáticamente estos atributos dispares en un paquete de parámetros unificado, como una estructura de kernel explícita o registros globales integrados, ejecuta las operaciones en paralelo y dispersa los resultados de salida a un búfer de salida para las etapas posteriores de la canalización de procesamiento. [ 28 ]

Los marcos de procesamiento de flujos modernos introducen abstracciones de primero en entrar, primero en salir (FIFO) para representar las canalizaciones de ejecución de datos como topologías direccionales desacopladas. Este diseño permite a los desarrolladores definir dependencias de paralelismo de datos explícitas, al tiempo que posibilita que el entorno de ejecución coordine de forma transparente la asignación de memoria, los límites de subprocesos y la planificación de tareas entre núcleos. [ 29 ]

Una implementación de este modelo de transmisión en C++ es RaftLib , una biblioteca de plantillas de código abierto que permite a los desarrolladores encadenar núcleos computacionales independientes en un grafo de flujo de datos utilizando operadores de flujo de C++ sobrecargados. [ 30 ] Para demostrar este paradigma, el siguiente código inicializa un flujo de generación de texto asíncrono vinculado a un núcleo de salida estándar:

import < raft > ; import < raftio > ;importar std ;usando String = std :: string ;using RaftKernel = raft :: kernel ; using RaftKernelStatus = raft :: kstatus ; using RaftMap = raft :: map ; using RaftPrint = raft :: print ;clase HelloWorld : public RaftKernel { public : HelloWorld () { output . addPort < String > ( "0" ); }virtual RaftKernelStatus run () { output [ "0" ]. push ( "Hola Mundo \n " ); return raft :: stop ; } };int main ( int argc , char * argv []) { // instanciar el kernel de impresión RaftPrint < String > p ;// instanciar el kernel hello world HelloWorld hello ;// crea un objeto de mapa RaftMap m ;// agregar kernels al mapa, tanto hello como p se ejecutan simultáneamente m += hello >> p ;// ejecutar el mapa m . exe ();devolver 0 ; }

Modelos de computación

Más allá de los lenguajes de programación procedimentales de alto nivel , las aplicaciones de procesamiento de flujos se estructuran formalmente mediante distintos modelos de computación (MoC) . Estos incluyen modelos de flujo de datos estructurados y marcos concurrentes basados ​​en procesos (como las redes de procesos de Kahn ), que representan matemáticamente las dependencias computacionales y las etapas de ejecución en paralelo. [ 31 ]

Comparación de arquitecturas de procesadores

Históricamente, las unidades centrales de procesamiento (CPU) de propósito general implementaron jerarquías de acceso a memoria de múltiples niveles cada vez más complejas para mitigar la creciente discrepancia de rendimiento entre las velocidades de ejecución brutas del núcleo y el ancho de banda de la memoria externa. Para enmascarar estas latencias de memoria, un porcentaje sustancial del área del chip de la CPU convencional se asigna al seguimiento automático de la caché, la predicción de bifurcaciones y la lógica de ejecución especulativa. En consecuencia, solo una pequeña fracción del espacio físico del hardware —históricamente estimada en menos del 10 %— se dedica directamente a las unidades aritmético-lógicas (ALU). [ 32 ]

Las estructuras de hardware de procesamiento de flujo minimizan esta sobrecarga de gestión aprovechando las restricciones explícitas del flujo de datos. [ 32 ] Estructuralmente, los procesadores de flujo suelen operar dentro de un entorno de coprocesamiento; una CPU principal del host sigue siendo responsable de ejecutar el sistema operativo, orquestar las asignaciones de recursos del sistema y gestionar los límites de los subprocesos a nivel de aplicación, mientras que el procesador de flujo se centra por completo en la aceleración aritmética de alto rendimiento. [ 33 ]

Para mantener el máximo rendimiento, los procesadores de flujo utilizan buses de memoria amplios y dedicados. Los primeros diseños empleaban barras cruzadas multisegmento con diferentes anchos de bus (como topologías de 128 o 256 bits), priorizando el ancho de banda de la memoria sobre la latencia. Esto contrasta con las plataformas de computación escalar históricas, que tradicionalmente dependían de canales de memoria de un solo canal más estrechos. Además, las rutas de acceso a la memoria dentro de un motor de flujo siguen siendo altamente predecibles; los límites de dimensión de los datos de flujo se fijan explícitamente al invocar el kernel, transformando indirecciones arbitrarias de múltiples punteros en cadenas de indirecciones limitadas que se resuelven en regiones de memoria de flujo explícitas. [ 32 ]

Debido a que las unidades de ejecución están organizadas en densos clústeres aritméticos paralelos gestionados por paradigmas de control convergentes VLIW y SIMD , las operaciones de lectura y escritura se procesan mediante transferencias de flujo masivo. Estos sistemas desacoplan los datos de aplicación intermedios, completando la gran mayoría de las tareas de cálculo directamente en el chip a través de una jerarquía explícita de ancho de banda de datos de tres niveles. [ 33 ]

Problemas de hardware en bucle

Aunque las arquitecturas de transmisión paralela pueden lograr una aceleración de un orden de magnitud, no todas las cargas de trabajo se benefician de este modelo. La latencia de la comunicación entre procesadores representa un cuello de botella significativo. Si bien los buses de sistema modernos, como PCI Express, proporcionan canales de comunicación dúplex completo de alto ancho de banda, la sobrecarga de latencia de la transferencia de datos entre la memoria del host y el espacio de memoria discreta del procesador de flujo sigue siendo considerable. En consecuencia, utilizar un coprocesador de flujo para conjuntos de datos pequeños suele ser ineficiente. Debido a que la reconfiguración del estado de ejecución o la compilación de un nuevo kernel introduce una latencia significativa, la arquitectura también conlleva graves penalizaciones de rendimiento al procesar dimensiones de flujo pequeñas, un fenómeno conocido como el efecto de flujo corto. [ 34 ]

El hardware gráfico programable inicial dependía en gran medida de profundas y especializadas canalizaciones de ejecución para maximizar el rendimiento. Sin embargo, los frecuentes cambios de estado, como el cambio de programas de sombreado o la actualización de enlaces de memoria, interrumpían la eficiencia de la canalización e introducían una gran sobrecarga de validación del controlador. Para mitigar estas desventajas en las canalizaciones de renderizado en tiempo real, los desarrolladores introdujeron patrones de optimización a nivel de software, como los "supersombreadores" (grandes núcleos monolíticos que manejan múltiples tipos de materiales mediante bifurcaciones condicionales) y los "atlas de texturas" (que consolidan recursos de textura independientes en una única disposición de memoria contigua para evitar cambios de enlace). Si bien estas técnicas se originaron en los motores de videojuegos reales, los principios subyacentes se aplican ampliamente al procesamiento de flujo genérico para maximizar el tiempo de ejecución del núcleo y evitar estados de bloqueo del hardware. [ 35 ]

Ejemplos históricos y evolución

Arquitectura dedicada desde los inicios

  • Commodore Amiga Blitter (1985): Una implementación temprana de hardware para la manipulación de datos tipo flujo. El Amiga blitter funcionaba como un coprocesador gráfico dedicado, capaz de combinar hasta tres fuentes de flujo de bits de memoria distintas mediante operaciones lógicas bit a bit para generar un único flujo de salida. Esta canalización movía datos a un ancho de banda de entrada máximo de 42 megabits por segundo, evitando la CPU principal para acelerar la renderización de gráficos 2D. [ 36 ]
  • Proyecto Stanford Imagine (1996-2002): Financiado por DARPA , Intel y Texas Instruments , este proyecto de investigación académica fue pionero en la arquitectura de flujo moderna. El proyecto desarrolló un prototipo de chip flexible que combinaba una matriz de unidades aritmético-lógicas (ALU) con un archivo de registro de flujo (SRF) centralizado y gestionado por software para maximizar la eficiencia energética y el rendimiento computacional.
  • Stanford Merrimac (2004): Una iniciativa académica posterior que extendió la arquitectura de transmisión Imagine al dominio de la supercomputación. Utilizó redes de interconexión especializadas para ofrecer altas relaciones rendimiento-precio para cargas de trabajo de computación científica en comparación con los clústeres de computadoras estándar de su época. [ 37 ]
  • Stream Processors, Inc. Storm-1 (2007): Un producto derivado del proyecto Stanford Imagine. La arquitectura Storm-1 estaba dirigida a mercados de procesamiento de señales digitales (DSP) de alta gama, como videoconferencias y vigilancia digital. Mejoró el rendimiento de 30 a 220 mil millones de operaciones por segundo (GOPS) mediante la agrupación de unidades aritmético-lógicas (ALU) de transmisión en un solo chip.

Unidades de procesamiento gráfico (GPU)

Las unidades de procesamiento gráfico (GPU) modernas representan la evolución comercial más extendida del procesamiento de flujos. Su progresión arquitectónica transformó el hardware de tuberías rígidas y de función fija a motores de flujo de propósito general: [ 38 ]

  • Era de funciones fijas (anterior a 2001): El hardware gráfico inicial no ofrecía acceso explícito para que los desarrolladores procesaran flujos de datos. Las operaciones de transmisión estaban completamente abstraídas dentro de las interfaces de programación de aplicaciones (API) gráficas, lo que limitaba la personalización del hardware.
  • Programabilidad temprana de vértices (2001-2002): Microarquitecturas como la ATI R200 y la Nvidia NV20 introdujeron el control explícito del programador, pero exclusivamente para las canalizaciones de procesamiento de vértices. El procesamiento de fragmentos/píxeles siguió ligado a paradigmas más antiguos. La total ausencia de ejecución condicional (compatibilidad con ramificaciones) limitó estos primeros chips a modelos matemáticos lineales simples, como simulaciones básicas de dinámica de fluidos.
  • Flujo de control dinámico (2003-2004): Arquitecturas como la ATI R300 y la Nvidia NV40 introdujeron un flujo de control y ramificación flexibles. Si bien estaban limitadas por el número máximo de instrucciones y la profundidad de anidamiento de bucles, estos chips permitían que los flujos de datos divergieran según los estados de cálculo en tiempo de ejecución.
  • Arquitecturas de flujo unificadas (2006-presente): Las generaciones posteriores unificaron las canalizaciones independientes de vértices y píxeles en matrices homogéneas de núcleos de flujo programables. Las iteraciones de hardware introdujeron mecánicas de flujo especializadas, como operaciones atómicas a nivel de hardware y búferes dinámicos de adición/consumo, lo que permitió la computación GPU compleja de propósito general (GPGPU). Esta evolución dio lugar a líneas de productos dedicadas a centros de datos para computación de alto rendimiento (HPC), incluidas las marcas Nvidia Tesla y AMD FireStream.

Motor de banda ancha celular

Desarrollado por una alianza de Sony, Toshiba e IBM (STI), el procesador Cell funciona como una arquitectura de transmisión híbrida cuando se combina con cadenas de herramientas de software especializadas. El chip cuenta con un procesador de control principal —el Elemento de Procesamiento de Potencia (PPE)— y una matriz de coprocesadores vectoriales denominados Elementos de Procesamiento Sinérgico (SPE). Dado que cada SPE posee un espacio de memoria de instrucciones y un contador de programa independientes, el chip se comporta como un entorno de instrucciones múltiples, datos múltiples (MIMD). Sin embargo, debido a las severas restricciones de memoria local, el software debe utilizar comandos explícitos de acceso directo a memoria (DMA) para transmitir datos secuencialmente a través de los SPE. Cuando los algoritmos de software se reestructuran por completo para adherirse estrictamente a este modelo de programación de transmisión, la eficiencia de ejecución del hardware iguala la de los procesadores de transmisión dedicados. [ 24 ]

Bibliotecas y lenguajes de programación de flujo

La mayoría de los marcos de procesamiento de flujos se basan en lenguajes de propósito general establecidos, como C , C++ o Java . Estos ecosistemas extienden las capacidades básicas del lenguaje mediante interfaces de programación de aplicaciones (API) dedicadas, directivas de compilador personalizadas o lenguajes específicos de dominio (DSL) personalizados para definir bloques de ejecución de kernel limitados y topologías de flujo. Además, los lenguajes de sombreado programables de alto nivel funcionan fundamentalmente como lenguajes de procesamiento de flujos orientados al hardware. [ 39 ]

Entornos académicos y de código abierto

  • Auto-Pipe: Desarrollado por el Laboratorio de Supercomputación Basada en Flujos (SBS) de la Universidad de Washington en St. Louis . Proporciona un entorno de desarrollo heterogéneo que coordina flujos de trabajo entre CPU (a través de C/C++ o Java), FPGA (a través de Verilog/VHDL ) y GPU (a través de CUDA ).
  • BeepBeep: Una biblioteca ligera de procesamiento de flujos de eventos basada en Java, desarrollada por el Laboratorio de Ciencias de la Computación Formal de la Universidad de Quebec en Chicoutimi .
  • Brook: Una extensión fundamental del lenguaje de transmisión de datos en paralelo desarrollada por la Universidad de Stanford para abstraer la programación de GPU.
  • Lenguaje de actores CAL : Un lenguaje de programación de flujo de datos de alto nivel diseñado para crear operadores con estado (actores) que transforman flujos de tokens entrantes en flujos de salida deterministas.
  • Cal2Many: Un marco de compilación de la Universidad de Halmstad que traduce el código de alto nivel de los actores CAL a código fuente de bajo nivel específico para cada plataforma, incluyendo C paralelo y modelos de descripción de hardware.
  • Lenguaje de programación DUP : Un lenguaje de programación de flujos desarrollado simultáneamente por la Universidad Técnica de Múnich y la Universidad de Denver .
  • HSTREAM: Una extensión de compilador de código fuente a código fuente basada en directivas, diseñada para facilitar el procesamiento de flujos de datos a través de recursos de ejecución heterogéneos de CPU y GPU, de forma similar a los patrones de compilación de OpenMP.
  • RaftLib : Una biblioteca de plantillas C++ de código abierto que utiliza operadores de flujo nativos de C++ (>>) para ensamblar núcleos computacionales concurrentes en topologías de flujo de datos unificadas. [ 30 ]
  • Sh : Una biblioteca de metaprogramación fundamental desarrollada en la Universidad de Waterloo para ejecutar programas de flujo en GPU, que sirvió como base de código para RapidMind .
  • S-Net: Un lenguaje de coordinación desarrollado en la Universidad de Hertfordshire que desacopla por completo la lógica de orquestación de flujos de los algoritmos estructurales.
  • SPar: Un lenguaje específico de dominio en C++ diseñado por el Grupo de Modelado de Aplicaciones (GMAP) de la Pontificia Universidad Católica de Rio Grande do Sul para expresar el paralelismo de flujos mediante anotaciones de atributos.
  • StreamIt: Un lenguaje especializado y una infraestructura de compilación desarrollada en el MIT, diseñada específicamente para optimizar las arquitecturas de procesamiento paralelo de flujos de datos.
  • WaveScript: Un lenguaje funcional de procesamiento de flujos de datos desarrollado en el MIT y optimizado para el manejo de flujos de sensores de alta velocidad y redes de señales distribuidas.

Arquitecturas comerciales y de propiedad privada

  • Embiot (Telchemy) : Un agente ligero e integrado de análisis de datos en tiempo real, diseñado para procesar flujos de sensores directamente en entornos de computación perimetral con recursos limitados.
  • Floodgate: Un motor de procesamiento de flujo que históricamente se incluía con el motor Gamebryo para gestionar la distribución de tareas multinúcleo en las consolas de videojuegos de consumo.
  • Jacket (AccelerEyes) : Un motor comercial diseñado para compilar y acelerar estructuras de cálculo de MATLAB directamente sobre unidades de flujo de GPU.
  • OpenHMPP : Un modelo de programación basado en directivas diseñado para simplificar el despliegue de kernels de streaming en aceleradores multinúcleo heterogéneos .
  • PeakStream : Una empresa derivada comercial del proyecto Stanford Brook, adquirida posteriormente por Google en 2007.
  • RapidMind : Una plataforma de software comercial que evolucionó a partir de la biblioteca Sh de la Universidad de Waterloo, posteriormente adquirida por Intel en 2009.
  • SPADE (IBM): El motor declarativo de aplicaciones de procesamiento de flujos, que sirve como lenguaje de transmisión declarativo fundamental para la plataforma empresarial System S de IBM. [ 40 ]
  • TStreams : Un entorno de ejecución declarativo para la transmisión de tareas desarrollado en el Laboratorio de Investigación de Hewlett-Packard en Cambridge para aprovechar la concurrencia multinúcleo.

Lenguajes de hardware específicos del proveedor

  • Brook+: Una implementación comercial del marco de lenguaje Stanford Brook , optimizada por AMD y acelerada por hardware .
  • CUDA (Compute Unified Device Architecture) : plataforma de computación paralela y modelo API propiedad de Nvidia para ejecutar kernels de transmisión en hardware gráfico.
  • Intel Ct : Extensión histórica del lenguaje C/C++ de Intel diseñada para vectorizar y transmitir automáticamente bucles de datos a través de procesadores multinúcleo.
  • StreamC: Un lenguaje de procesamiento de flujos desarrollado por Stream Processors, Inc. , basado directamente en la microarquitectura del procesador Stanford Imagine.

Motores de procesamiento de eventos distribuidos y de eventos complejos (CEP)

  • Apache NiFi : Un sistema integrado de logística de datos diseñado para automatizar y gestionar el flujo continuo de datos en forma de grafos dirigidos entre sistemas de software.
  • Apama: Un motor de análisis y procesamiento de eventos complejos de alto rendimiento y baja latencia, desarrollado por Software AG.
  • Wallaroo: Un marco de procesamiento de flujos elásticos distribuidos de código abierto diseñado para el manejo de métricas de baja latencia.
  • WSO2 Stream Processor / Siddhi: Un motor de procesamiento de eventos complejos y de transmisión de código abierto, nativo de la nube, que ingiere, analiza y reacciona a flujos en tiempo real mediante consultas similares a SQL.

Ecosistemas de ejecución distribuidos y a escala de nube

La infraestructura de datos moderna a escala de clúster clasifica las arquitecturas de flujo en función de sus modelos de ejecución:

  • Procesamiento nativo de flujo continuo: Marcos de trabajo que procesan los elementos individualmente a medida que llegan, optimizando para latencias en tiempo real inferiores a un segundo:
    • Apache Storm : Un sistema de computación distribuida en tiempo real, nativo y de baja latencia.
    • Apache Flink : Un verdadero motor de ejecución de flujos de datos que trata la computación por lotes estrictamente como un subconjunto especializado del procesamiento continuo de flujos de datos.
    • Apache Samza : Un motor de procesamiento de flujos distribuidos con estado, construido sobre Apache Kafka.
  • Procesamiento de flujos por micro-lotes: Marcos de trabajo que logran una semántica de flujo de alto rendimiento mediante la recopilación automática de elementos entrantes en ventanas de tiempo muy restringidas o lotes en miniatura:
    • Apache Spark Streaming : Una extensión de la API principal de Apache Spark que ingiere flujos de datos en tiempo real y los procesa en pequeños fragmentos discretos (microlotes).
  • Arquitecturas de registro distribuido: Infraestructura que sirve como capa de transporte persistente y de solo adición para arquitecturas de flujo continuo:
    • Apache Kafka : Una plataforma de transmisión de eventos distribuida y altamente escalable que se utiliza para ingerir y almacenar flujos de registros tolerantes a fallos.

Servicios de transmisión en la nube gestionados

  • Amazon Web Services (AWS) Kinesis : Un servicio en la nube gestionado para el procesamiento en tiempo real de flujos de datos distribuidos a gran escala.
  • Google Cloud Dataflow : Un servicio en la nube totalmente administrado que ejecuta canalizaciones unificadas de procesamiento por lotes y en tiempo real basadas en la arquitectura Apache Beam.
  • IBM Streams / Streaming Analytics: Entornos de ejecución en la nube y locales para aplicaciones de streaming de baja latencia escritas en SPL .
  • Microsoft Azure Stream Analytics : Un motor de procesamiento de eventos complejos en tiempo real administrado, diseñado para evaluar flujos de datos provenientes de aplicaciones y dispositivos IoT.
  • Procesamiento de flujos de MongoDB Atlas: Un motor de enrutamiento de flujos de bases de datos gestionadas, diseñado para procesar y agregar continuamente los cambios activos en los documentos.
  • SQLStreamBuilder (Eventador): Una interfaz gestionada que permite la detección continua de patrones complejos en estructuras de Kafka mediante consultas SQL declarativas estándar.

Véase también

Referencias

  1. 1 2 Breve introducción al procesamiento de flujos de datos
  2. FCUDA: Permite la compilación eficiente de kernels CUDA en FPGAs
  3. ^ Rixner , Scott; Dally, William J.; Kapasi, Ujval J.; Khailany, Brucek; López-Lagunas, Abelardo; Mattson, Peter R.; Owens, John D. (1998). "Una arquitectura con ancho de banda eficiente para el procesamiento de medios" (PDF) . Micro . 31 .
  4. "El procesador de flujo Imagine" . Actas. Conferencia Internacional IEEE sobre Diseño de Computadoras: VLSI en Computadoras y Procesadores . 2002. págs. 141–146 . doi : 10.1109/ICCD.2002.1106783 . 
  5. AliciaLiMicrosoft. "JOIN - Consulta de análisis de flujo" . learn.microsoft.com . Consultado el 9 de julio de 2026 .
  6. Luckham, David C. (2002). El poder de los eventos: una introducción al procesamiento de eventos complejos en sistemas empresariales distribuidos . Boston: Addison-Wesley. ISBN 978-0-201-72789-0.
  7. 1 2 Flynn, Michael J. (septiembre de 1972). "Algunas organizaciones informáticas y su eficacia" . IEEE Transactions on Computers . C-21 (9): 948– 960. doi : 10.1109/TC.1972.5009071 . ISSN 1557-9956 . 
  8. 1 2 Hennessy, John L.; Patterson, David A.; Kozyrakis, Christos (2026). Arquitectura de computadoras: un enfoque cuantitativo (Séptima ed.). San Francisco: Morgan Kaufmann Publishers, un sello editorial de Elsevier. ISBN  978-0-443-15407-2.
  9. "Tesis doctoral "Microprocesadores vectoriales" de Krste Asanović" . people.eecs.berkeley.edu . Consultado el 9 de julio de 2026 .
  10. Fisher, Randall J.; Dietz, Henry G. (1999). Chatterjee, Siddhartha; Prins, Jan F.; Carter, Larry; Ferrante, Jeanne; Li, Zhiyuan; Sehr, David; Yew, Pen-Chung (eds.). "Compiling for SIMD Within a Register" . Languages ​​and Compilers for Parallel Computing . Berlín, Heidelberg: Springer: 290–305 . doi : 10.1007/3-540-48319-5_19 . ISBN 978-3-540-48319-9.
  11. "Manual de referencia de optimización de arquitecturas Intel® 64 e IA-32, volumen 1" . Intel . Consultado el 9 de julio de 2026 .
  12. 1 2 3 Stephens, Robert (1997-07-01). "Una revisión del procesamiento de flujos" . Acta Informatica . 34 (7): 491– 541. doi : 10.1007/s002360050095 . ISSN 1432-0525 . 
  13. Revista IEEE de Circuitos de Estado Sólido: "Un procesador de flujo programable de 512 GOPS para procesamiento de señales, imágenes y vídeo" , Universidad de Stanford y Stream Processors, Inc.
  14. Khailany, Dally, Rixner, Kapasi, Owens y Towles: "Explorando la escalabilidad VLSI de los procesadores de flujo" , Universidad de Stanford y Universidad Rice.
  15. Kapasi, UJ; Dally, WJ; Ahn, JH; Mattson, P.; Owens, JD (2003). "Procesadores de flujo programables" . IEEE Computer . 36 (8).
  16. Gummaraju y Rosenblum, "Procesamiento de flujos en procesadores de propósito general" , Universidad de Stanford.
  17. Kapasi, Dally, Rixner, Khailany, Owens, Ahn y Mattson, "Procesadores de corriente programables" , Universidades de Stanford, Rice, California (Davis) y Reservoir Labs.
  18. Owens, John D.; Luebke, David; Govindaraju, Naga; Harris, Mark; Krüger, Jens; Lefohn, Aaron E.; Purcell, Timothy J. (2005). "Un estudio sobre computación de propósito general en hardware gráfico" (PDF) . Eurographics .
  19. "Un sistema de sombreado procedimental en tiempo real para hardware gráfico programable" . graphics.stanford.edu . Consultado el 9 de julio de 2026 .
  20. "Merrimac - Proyecto de supercomputadora de transmisión de Stanford" . Sitio web del grupo . Archivado del original el 18 de diciembre de 2013. Consultado el 9 de marzo de 2017 .
  21. "Arquitectura de flujo" . cva.stanford.edu . Consultado el 9 de julio de 2026 .
  22. "StreamIt" . groups.csail.mit.edu . Consultado el 9 de julio de 2026 .
  23. Thies, William; Karczmarek, Michał; Amarasinghe, Saman (2002). "StreamIt: Un lenguaje para aplicaciones de transmisión" (PDF) . CC '02: Actas de la 11.ª Conferencia Internacional sobre Construcción de Compiladores .
  24. 1 2 Johns, CR; Brokenshire, DA (2007-09-01). "Introducción a la arquitectura del motor de banda ancha celular" . IBM Journal of Research and Development . 51 (5): 503– 519. doi : 10.1147/rd.515.0503 . ISSN 0018-8646 . 
  25. ^ Homann , Holger; Laenen, Francois (10 de octubre de 2017). "SoAx: una estructura genérica de matrices en C++ para manejar partículas en códigos HPC" . arXiv.org . Consultado el 9 de julio de 2026 .
  26. Sharp, Amanda K. "Transformaciones de la disposición de la memoria" . Intel . Consultado el 9 de julio de 2026 .
  27. "Especificación de vértices - Wiki de OpenGL" . wikis.khronos.org . Archivado del original el 17 de febrero de 2026. Consultado el 9 de julio de 2026 .
  28. "Atributos | luma.gl" . luma.gl . Archivado del original el 19-06-2025 . Recuperado el 09-07-2026 .
  29. Beard, JC; Li, P.; Chamberlain, RD (2015). "RaftLib: Una biblioteca de plantillas de C++ para el procesamiento paralelo de flujos de alto rendimiento" (PDF) . Conferencia Internacional sobre Programación Paralela . doi : 10.1145/2712386.2712400 .
  30. 1 2 RaftLib/RaftLib , RaftLib, 2026-07-08 , recuperado el 2026-07-09
  31. Lee, EA; Parks, TM (1995). "Redes de procesos de flujo de datos" (PDF) . Actas del IEEE . 83 (5): 773–801 .
  32. 1 2 3 Dally, WJ; Kapasi, UJ; Khailany, B.; Ahn, JH (2004). Procesamiento de flujos en Imagine (PDF) . Laboratorio de Sistemas Informáticos de la Universidad de Stanford.
  33. 1 2 Rixner, S. (2001). Arquitectura de procesadores de flujo (Ph.D.). Universidad de Stanford.
  34. Dally, Bill (28 de mayo de 2002). "Descripción general del procesamiento de flujos" (PDF) .
  35. Trapp, Matthias; Döllner, Jürgen (2007-07-03). "Combinación automatizada de programas de sombreado en tiempo real" . Eurographics 2007 Shortpaper : 53–56 .
  36. Commodore-Amiga, Inc., ed. (1989). Manual de referencia de hardware de Amiga . Serie de referencia técnica de Amiga (Edición revisada y actualizada ). Reading, Mass.: Addison-Wesley. ISBN  978-0-201-18157-9.
  37. Dally, William J.; Labonte, Francois; Das, Abhishek; Hanrahan, Patrick; Ahn, Jung-Ho; Gummaraju, Jayanth; Erez, Mattan; Jayasena, Nuwan; Buck, Ian; Knight, Timothy J.; Kapasi, Ujval J. (15 de noviembre de 2003). "Merrimac: Supercomputación con flujos" . SC '03: Actas de la conferencia ACM/IEEE de 2003 sobre supercomputación . ACM: 35. doi : 10.1145/1048935.1050187 . ISBN 978-1-58113-695-1.
  38. "CSDL | IEEE Computer Society" . www.computer.org . Consultado el 9 de julio de 2026 .
  39. Memeti, Suejb; Pllana, Sabri (octubre de 2018). "HSTREAM: una extensión de lenguaje basada en directivas para computación de flujo heterogénea" . 2018 IEEE International Conference on Computational Science and Engineering (CSE) : 138–145 . doi : 10.1109/CSE.2018.00026 .
  40. Gedik, Bugra; Andrade, Henrique; Wu, Kun-Lung; Yu, Philip S.; Doo, Myungcheol (09-06-2008). "SPADE: el motor de procesamiento de flujo declarativo del sistema" . Actas de la conferencia internacional ACM SIGMOD 2008 sobre gestión de datos . SIGMOD '08. Nueva York, NY, EE. UU.: Association for Computing Machinery: 1123–1134 . doi : 10.1145/1376616.1376729 . ISBN 978-1-60558-102-6.