En programación de computadoras , la programación de flujo de datos es un paradigma de programación que modela un programa como un gráfico dirigido de los datos que fluyen entre operaciones, implementando así los principios y la arquitectura del flujo de datos . [1] Los lenguajes de programación de flujo de datos comparten algunas características de los lenguajes funcionales y generalmente se desarrollaron para llevar algunos conceptos funcionales a un lenguaje más adecuado para el procesamiento numérico. Algunos autores utilizan el término flujo de datos en lugar de flujo de datos para evitar confusiones con la computación de flujo de datos o la arquitectura de flujo de datos , basada en un paradigma de máquina indeterminista. La programación de flujo de datos fue iniciada por Jack Dennis y sus estudiantes de posgrado en el MIT en la década de 1960.
Tradicionalmente, un programa se modela como una serie de operaciones que suceden en un orden específico; esto puede denominarse secuencial, [2] : p.3 procedimental, [3] flujo de control [3] (que indica que el programa elige una ruta específica) o programación imperativa . El programa se centra en comandos, en línea con la visión de von Neumann [2] : p.3 de la programación secuencial, donde los datos normalmente están "en reposo". [3] : pág.7
Por el contrario, la programación de flujo de datos enfatiza el movimiento de datos y modela programas como una serie de conexiones. Las entradas y salidas explícitamente definidas conectan operaciones, que funcionan como cajas negras . [3] : p.2 Una operación se ejecuta tan pronto como todas sus entradas sean válidas. [4] Por lo tanto, los lenguajes de flujo de datos son inherentemente paralelos y pueden funcionar bien en sistemas grandes y descentralizados. [2] : pág.3 [5] [6]
Uno de los conceptos clave en programación de computadoras es la idea de estado , esencialmente una instantánea de varias condiciones en el sistema. La mayoría de los lenguajes de programación requieren una cantidad considerable de información de estado, que generalmente está oculta al programador. A menudo, la propia computadora no tiene idea de qué información codifica el estado duradero. Este es un problema grave, ya que la información de estado debe compartirse entre múltiples procesadores en máquinas de procesamiento en paralelo . La mayoría de los lenguajes obligan al programador a agregar código adicional para indicar qué datos y partes del código son importantes para el estado. Este código tiende a ser costoso en términos de rendimiento y difícil de leer o depurar. El paralelismo explícito es una de las principales razones del bajo rendimiento de los Enterprise Java Beans al crear aplicaciones que no utilizan OLTP y hacen un uso intensivo de datos . [ cita necesaria ]
Mientras que un programa secuencial puede imaginarse como un solo trabajador que se mueve entre tareas (operaciones), un programa de flujo de datos se parece más a una serie de trabajadores en una línea de ensamblaje , cada uno de los cuales realiza una tarea específica siempre que haya materiales disponibles. Dado que las operaciones sólo se ocupan de la disponibilidad de las entradas de datos, no tienen ningún estado oculto que rastrear y están todas "listas" al mismo tiempo.
Los programas de flujo de datos se representan de diferentes maneras. Un programa tradicional generalmente se representa como una serie de instrucciones de texto, lo cual es razonable para describir un sistema en serie que canaliza datos entre pequeñas herramientas de propósito único que reciben, procesan y devuelven. Los programas de flujo de datos comienzan con una entrada, tal vez los parámetros de la línea de comando , e ilustran cómo se usan y modifican esos datos. El flujo de datos es explícito, a menudo ilustrado visualmente como una línea o tubería.
En términos de codificación, un programa de flujo de datos podría implementarse como una tabla hash , con entradas identificadas de forma única como claves, utilizadas para buscar punteros a las instrucciones. Cuando se completa cualquier operación, el programa escanea la lista de operaciones hasta que encuentra la primera operación donde todas las entradas son actualmente válidas y la ejecuta. Cuando finaliza esa operación, normalmente generará datos, lo que hará que otra operación sea válida.
Para operación paralela, solo es necesario compartir la lista; es el estado de todo el programa. Por lo tanto, la tarea de mantener el estado se elimina del programador y se entrega al tiempo de ejecución del lenguaje . En máquinas con un único núcleo de procesador donde una implementación diseñada para operación paralela simplemente introduciría una sobrecarga, esta sobrecarga se puede eliminar por completo utilizando un tiempo de ejecución diferente.
Algunas bibliotecas de flujo de datos recientes, como Differential/Timely Dataflow, han utilizado computación incremental para un procesamiento de datos mucho más eficiente. [1] [7] [8]
Un lenguaje de flujo de datos pionero fue BLODI (BLOck DIagram), publicado en 1961 por John Larry Kelly, Jr. , Carol Lochbaum y Victor A. Vyssotsky para especificar sistemas de datos muestreados . [9] Se compiló una especificación BLODI de unidades funcionales (amplificadores, sumadores, líneas de retardo, etc.) y sus interconexiones en un solo bucle que actualizaba todo el sistema durante un tic de reloj.
En un doctorado de 1966. tesis, La especificación gráfica en línea de procedimientos informáticos , [10] Bert Sutherland creó uno de los primeros marcos de programación de flujo de datos gráficos para facilitar la programación paralela. Los lenguajes de flujo de datos posteriores se desarrollaron a menudo en grandes laboratorios de supercomputadoras . POGOL, un lenguaje de procesamiento de datos convencional desarrollado en la NSA , compiló aplicaciones a gran escala compuestas de múltiples operaciones de archivo a archivo, por ejemplo fusionar, seleccionar, resumir o transformar, en código eficiente que eliminaba la creación o escritura en archivos intermedios. archivos en la mayor medida posible. [11] SISAL , un popular lenguaje de flujo de datos desarrollado en el Laboratorio Nacional Lawrence Livermore , se parece a la mayoría de los lenguajes basados en declaraciones, pero las variables deben asignarse una vez . Esto permite al compilador identificar fácilmente las entradas y salidas. Se han desarrollado varias ramificaciones de SISAL, incluido SAC , Single Assignment C , que intenta permanecer lo más cercano posible al popular lenguaje de programación C.
La Marina de los Estados Unidos financió el desarrollo de ACOS y SPGN (notación gráfica de procesamiento de señales) a principios de los años 1980. Esto se utiliza en varias plataformas en el campo hoy en día. [12]
Un concepto más radical es Prograph , en el que los programas se construyen como gráficos en pantalla y las variables se reemplazan por completo con líneas que vinculan las entradas con las salidas. Por cierto, Prograph se escribió originalmente en Macintosh , que permaneció con un solo procesador hasta la introducción del DayStar Genesis MP en 1996. [ cita necesaria ]
Existen muchas arquitecturas de hardware orientadas a la implementación eficiente de modelos de programación de flujo de datos. [ vago ] La arquitectura de flujo de datos de tokens etiquetados del MIT fue diseñada por Greg Papadopoulos . [ peso excesivo? ]
El flujo de datos ha sido propuesto [ ¿ por quién? ] como una abstracción para especificar el comportamiento global de los componentes del sistema distribuido: en el modelo de programación de objetos distribuidos en vivo , los flujos de datos distribuidos se utilizan para almacenar y comunicar el estado y, como tales, desempeñan un papel análogo a las variables, campos y parámetros en Lenguajes de programación similares a Java.
Los lenguajes de programación de flujo de datos incluyen: