En programación informática , 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, en general, 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] de flujo de control [3] (que indica que el programa elige una ruta específica) o programación imperativa . El programa se centra en los 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.7
Por el contrario, la programación de flujo de datos enfatiza el movimiento de datos y modela los programas como una serie de conexiones. Las entradas y salidas definidas explícitamente conectan operaciones, que funcionan como cajas negras . [3] : p.2 Una operación se ejecuta tan pronto como todas sus entradas se vuelven 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.3 [5] [6]
Uno de los conceptos clave en la programación informática es la idea de estado , que es 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 para el programador. A menudo, la computadora en sí no tiene idea de qué pieza de información codifica el estado duradero. Este es un problema grave, ya que la información de estado debe compartirse entre varios procesadores en máquinas de procesamiento 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, así como difícil de leer o depurar. El paralelismo explícito es una de las principales razones del bajo rendimiento de Enterprise Java Beans al crear aplicaciones intensivas en datos y no OLTP . [ cita requerida ]
Mientras que un programa secuencial puede imaginarse como un solo trabajador que se mueve entre tareas (operaciones), un programa de flujo de datos es más como una serie de trabajadores en una línea de montaje , cada uno de los cuales realiza una tarea específica siempre que haya materiales disponibles. Dado que las operaciones solo se ocupan de la disponibilidad de entradas de datos, no tienen un estado oculto que rastrear y todas están "listas" al mismo tiempo.
Los programas de flujo de datos se representan de distintas maneras. Un programa tradicional suele representarse como una serie de instrucciones de texto, lo que resulta razonable para describir un sistema en serie que canaliza datos entre pequeñas herramientas de un solo propósito 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 comandos , e ilustran cómo se utilizan y modifican esos datos. El flujo de datos es explícito, a menudo se ilustra visualmente como una línea o tubería.
En términos de codificación, un programa de flujo de datos se puede implementar como una tabla hash , con entradas identificadas de forma única como claves, que se utilizan para buscar punteros a las instrucciones. Cuando se completa una operación, el programa escanea la lista de operaciones hasta que encuentra la primera operación en la que todas las entradas son válidas actualmente y la ejecuta. Cuando esa operación termina, normalmente generará datos, lo que hará que otra operación sea válida.
Para el funcionamiento en paralelo, solo es necesario compartir la lista; es el estado de todo el programa. De esta forma, la tarea de mantener el estado se elimina del programador y se le asigna al entorno de ejecución del lenguaje . En máquinas con un solo núcleo de procesador, donde una implementación diseñada para el funcionamiento en paralelo simplemente generaría sobrecarga, esta sobrecarga se puede eliminar por completo utilizando un entorno de ejecución diferente.
Algunas bibliotecas de flujo de datos recientes, como Differential/Timely Dataflow, han utilizado la computación incremental para un procesamiento de datos mucho más eficiente. [1] [7] [8]
Un lenguaje de flujo de datos pionero fue BLOck DIagram (BLODI), publicado en 1961 por John Larry Kelly, Jr. , Carol Lochbaum y Victor A. Vyssotsky para especificar sistemas de datos muestreados . [9] Una especificación BLODI de unidades funcionales (amplificadores, sumadores, líneas de retardo, etc.) y sus interconexiones se compiló en un solo bucle que actualizaba todo el sistema para un tic de reloj.
En una tesis doctoral de 1966, The On-line Graphical Specification of Computer Procedures , [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 los 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 un código eficiente que eliminó la creación o escritura en archivos intermedios en la mayor medida posible. [11] SISAL , un lenguaje de flujo de datos popular 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 derivaciones de SISAL, incluido SAC , Single Assignment C , que intenta permanecer lo más cerca posible del popular lenguaje de programación C.
La Marina de los Estados Unidos financió el desarrollo de la notación gráfica de procesamiento de señales (SPGN) y ACOS a principios de la década de 1980. Hoy en día, se utiliza en varias plataformas en el campo. [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 siguió siendo un sistema de un solo procesador hasta la introducción del DayStar Genesis MP en 1996. [ cita requerida ]
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 token etiquetado del MIT fue diseñada por Greg Papadopoulos . [ ¿ Peso excesivo? – discutir ]
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: