Stream processing

Uses your system voice; voice and rate in settings.

Snapshot

≈ 10 min read

Names in other languages

No names in other languages are held for this entry yet.

Article bodies are English and are not machine-translated. A name in another language is not a translation of the article.

In computer science, stream processing (also known as event stream processing, data stream processing, or distributed stream processing) is a programming paradigm that views streams, or sequences of events in time, as the central input and output objects of computation. Stream processing encompasses dataflow programming, reactive programming, and distributed data processing. Stream processing systems use streaming algorithms to trace parallel processing for data streams. The software stack for these systems includes components such as programming models and query languages, for expressing computation; stream management systems for distribution and scheduling; and hardware components for acceleration, including floating-point units, graphics processing units, and field-programmable gate arrays. The stream processing paradigm simplifies parallel software and hardware by restricting the kinds of parallel computation that can be performed. Given a sequence of data (a stream), a series of operations (kernel functions) is applied to each element in the stream. Kernel functions are usually pipelined, and efficient local on-chip memory reuse is attempted in order to minimize bandwidth loss associated with external memory interaction. Uniform streaming, in which a single kernel function is applied to all elements in the stream, is typical.…

In computer science, stream processing (also known as event stream processing, data stream processing, or distributed stream processing) is a programming paradigm that views streams, or sequences of events in time, as the central input and output objects of computation. Stream processing encompasses dataflow programming, reactive programming, and distributed data processing. Stream processing systems use streaming algorithms to trace parallel processing for data streams. The software stack for these systems includes components such as programming models and query languages, for expressing computation; stream management systems for distribution and scheduling; and hardware components for acceleration, including floating-point units, graphics processing units, and field-programmable gate arrays. The stream processing paradigm simplifies parallel software and hardware by restricting the kinds of parallel computation that can be performed. Given a sequence of data (a stream), a series of operations (kernel functions) is applied to each element in the stream. Kernel functions are usually pipelined, and efficient local on-chip memory reuse is attempted in order to minimize bandwidth loss associated with external memory interaction. Uniform streaming, in which a single kernel function is applied to all elements in the stream, is typical. Because the kernel and stream abstractions expose data dependencies, compiler tools can fully automate and optimize on-chip management tasks. Stream processing hardware can use techniques such as scoreboarding to initiate direct memory access (DMA) when dependencies are resolved. The elimination of manual DMA management reduces software complexity, while the reduced reliance on hardware cached I/O decreases the memory footprint required by specialized computational units such as arithmetic logic units. During the 1980s stream processing was explored within dataflow programming. One example is the language SISAL. ==Code examples== By way of illustration, the following code fragments demonstrate the detection of patterns within event streams. The first example shows the processing of a data stream using a continuous SQL query: an ongoing query that processes incoming data based on timestamps and window duration. This code fragment illustrates a JOIN of two data streams: one representing stock and the other representing the resulting stock . The query outputs a stream of all orders matched by a trade within one second of the order being placed. The output stream is sorted by timestamp; in this case, the timestamp originates from the stream. 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; Another sample code fragment detects weddings within a stream of external events, such as church bells ringing, the appearance of a man in a tuxedo or morning suit, a woman in a white gown, and rice being thrown. A "complex" or "composite" event is the high-level event inferred from these constituent events: in this case, that a wedding is occurring. WHEN Person.Gender EQUALS "man" AND Person.Clothes EQUALS "tuxedo" FOLLOWED-BY Person.Clothes EQUALS "gown" AND (Church_Bell OR Rice_Flying) WITHIN 2 hours ACTION Wedding for (int i = 0; i While structural variations exist—such as the use of nested inner loops or array-of-structures data layouts—the underlying computation relies fundamentally on this linear execution model. ===Parallel SIMD paradigm, packed registers (SWAR)=== // for each vector for (int elem = 0; elem This model abstractly demonstrates the paradigm by assuming a generic vector_sum instruction. While this abstraction reflects how instruction intrinsics operate in practice, it omits underlying hardware implementation details—such as explicit data formats and component bit-widths—for clarity. By operating on packed data structures, this method reduces the number of individual arithmetic instructions required to process the array components. Loop control and jump overhead are also reduced due to the lower iteration count. These efficiency gains are the direct result of executing multiple arithmetic operations simultaneously within a single instruction execution step. However, because a packed SIMD register has a fixed bit-width capacity, scalability is inherently bounded by the maximum register size. In this scenario, hardware acceleration is capped by the vector width of four parallel operations, a configuration standard in architectures such as AltiVec and Streaming SIMD Extensions (SSE). ===Parallel stream paradigm (SIMD/MIMD)=== // This is a fictional language for demonstration purposes. elements = array streamElement([number, number)[100] kernel = instance streamKernel("@arg0[@iter]") result = kernel.invoke(elements) In the stream processing paradigm, data is treated as an unbounded, continuous sequence of elements rather than a static dataset. Instead of managing iteration explicitly, the program defines a dataflow sequence, allowing the execution environment to apply the compute kernel function automatically as new data elements arrive. Although a 1:1 mapping between input and output data is commonly used for simplicity, it is not an inherent architectural requirement; kernels can perform complex transformations, aggregation windows, or stateful modifications. Compilers optimized for this paradigm can perform extensive automated code transformations, such as loop unrolling. This abstraction allows throughput to scale transparently with hardware capacity, enabling the utilization of hundreds of arithmetic logic units (ALUs). Minimizing complex, unpredictable data access patterns ensures that a higher percentage of the hardware's peak execution capacity is accessible. While stream processing shares characteristics with broader SIMD and MIMD architectures, the concepts remain distinct. Although SIMD hardware often executes operations in a pipelined or streaming manner, standard SIMD performance characteristics differ; the stream processing model enforces structured dataflow and explicit memory management that permits significantly higher execution efficiency. When implemented on general-purpose architectures such as standard CPUs, stream processing abstractions frequently yielded limited performance gains, with some historical studies noting an execution speedup of only approximately 1.5x. In contrast, early dedicated stream processors achieved performance increases exceeding 10x, primarily due to specialized hardware-managed register files and higher levels of parallel execution units. Despite variations in flexibility across implementation models, stream processing hardware generally imposes strict constraints on both kernel complexity and stream dimension sizes. For example, consumer-grade graphics processing hardware historically lacked high-precision arithmetic support, lacked complex pointer indirection capabilities, and enforced strict limits on maximum instruction counts. // A particle in a three-dimensional space. struct Particle { double x; double y; double z; // 8 bit per channel, say we care about RGB only unsigned byte color[3]; float size; // ... and many other attributes may follow... }; When multiple entities exist in sequence, they are allocated end-to-end, forming an array of structures (AoS) topology. If an algorithm processes only a single attribute across all elements—such as modifying only the 3D coordinates—the execution engine must skip over the unused attributes in memory. Because conventional cache lines fetch memory in contiguous blocks, loading unneeded attributes results in inefficient cache utilization and wasted memory bandwidth. Furthermore, standard SIMD operations require input elements to be contiguous and properly aligned in memory to fill vector lanes efficiently. To optimize data streaming and vector execution, attributes can be separated into distinct parallel blocks using a structure of arrays (SoA) layout. An SoA representation isolates identical fields into individual, contiguous arrays, as shown below: struct Particle { double* x; double* y; double* z; unsigned byte* colorRed; unsigned byte* colorBlue; unsigned byte* colorGreen; float* size; }; While the structure of arrays (SoA) layout optimizes uniform data paths, it introduces distinct architectural trade-offs. If a routine must simultaneously operate on multiple disparate attributes of a single entity, those attributes may reside far apart in virtual memory, resulting in severe cache misses and increased address translation overhead. Furthermore, ensuring that each separate array meets hardware memory alignment boundaries can necessitate data padding, which increases overall memory footprints. Dynamic memory management also becomes highly complex when elements must be added or removed, as modifications require shifting elements synchronously across multiple disconnected arrays. Conversely, dedicated stream processing architectures heavily utilize structured abstractions to unify these layouts. In contemporary graphics processing units (GPU) vertex pipelines, hardware provides a fixed number of attribute slots—historically standardizing around 16 input lines. The application specifies the component count and data type format for each input stream, though hardware support is typically restricted to primitive numeric data types. These independent attributes are bound to a cohesive memory block via an explicit stride parameter. By adjusting the byte stride between consecutive array elements, developers can format the data stream as either interleaved arrays of structures (AoS) or separate structures of arrays (SoA). At the execution stage, the GPU hardware automatically gathers these disparate attributes into a unified parameter packet—such as an explicit kernel structure or built-in global registers—executes the operations in parallel, and scatters the output results to an output buffer for subsequent processing pipeline stages. Modern stream processing frameworks introduce first-in, first-out (FIFO) abstractions to represent data execution pipelines as decoupled, directional topologies. This design allows developers to define explicit data-parallel dependencies while enabling the runtime environment to coordinate memory allocation, threading boundaries, and cross-kernel task scheduling transparently. An implementation of this streaming model in C++ is RaftLib, an open-source template library that enables developers to chain independent computational kernels into a dataflow graph using overloaded C++ stream operators. To demonstrate this paradigm, the following code initializes an asynchronous text-generation stream linked to a standard output kernel: import ; import ; import std; using String = std::string; using RaftKernel = raft::kernel; using RaftKernelStatus = raft::kstatus; using RaftMap = raft::map; using RaftPrint = raft::print; class HelloWorld : public RaftKernel { public: HelloWorld() { output.addPort ("0"); } virtual RaftKernelStatus run() { output["0"].push("Hello World\n"); return raft::stop; } }; int main(int argc, char* argv[]) { // instantiate print kernel RaftPrint p; // instantiate hello world kernel HelloWorld hello; // make a map object RaftMap m; // add kernels to map, both hello and p are executed concurrently m += hello >> p; // execute the map m.exe(); return 0; }

Text derived from https://en.wikipedia.org/w/index.php?oldid=1371528499 under CC BY-SA 4.0; modifications have been made.