Stream and Vector Data Converters
Relevant source files
The following files were used as context for generating this wiki page:
Stream and Vector Data Converters in gr-cuda provide essential structural manipulation of data within the GPU-accelerated pipeline. These blocks allow for the conversion between single-item streams and vectored data (blocking), as well as the interleaving and deinterleaving of multiple streams.
These converters are implemented as CUDA-enabled GNU Radio blocks, allowing for zero-copy or device-side data reformatting. By utilizing cuda_block as a base class, these components maintain the managed CUDA stream and synchronization mechanisms required for high-performance GPU signal processing.
Sources: include/gnuradio/cuda/vector_to_stream.h, lib/vector_to_streams_impl.h:15-20, python/cuda/qa_stream_operators.py:16-25
Architectural Overview
The converters are divided into two primary categories: dimensionality changes (Stream-to-Vector and Vector-to-Stream) and stream multiplexing (Streams-to-Vector and Vector-to-Streams).
Dimensionality Converters
These blocks change the items per buffer without changing the total number of streams.
- Stream to Vector: Aggregates
Nindividual items into a single vector of lengthN. - Vector to Stream: Breaks a vector of length
NintoNindividual items on a single stream.
Multiplexing Converters (Interleaving)
These blocks handle the transition between parallel streams and interleaved vectored data.
- Streams to Vector (Interleave): Takes
Ninput streams and interleaves them into a single stream of vectors. - Vector to Streams (Deinterleave): Takes a single stream of vectors and distributes the vector elements across
Noutput streams.
The following diagram illustrates the relationship between these converter types:
This diagram shows the logical flow of data through dimensionality and multiplexing converters.
Sources: include/gnuradio/cuda/stream_to_vector.h, include/gnuradio/cuda/streams_to_vector.h, include/gnuradio/cuda/vector_to_stream.h, include/gnuradio/cuda/vector_to_streams.h
Key Components and API
Block Classes
The converters inherit from standard GNU Radio parent classes while integrating CUDA functionality.
| Class Name | Inheritance | Purpose |
|---|---|---|
stream_to_vector | sync_decimator | Converts items to vectors (Decimation in terms of item count) |
vector_to_stream | sync_interpolator | Converts vectors to items (Interpolation in terms of item count) |
streams_to_vector | sync_block | Interleaves multiple streams into vectors |
vector_to_streams | sync_block | Deinterleaves vectors into multiple streams |
Sources: include/gnuradio/cuda/vector_to_stream.h:18-20, include/gnuradio/cuda/vector_to_streams.h:18-20, lib/vector_to_streams_impl.h:15-18
Configuration Parameters
The make functions for these blocks require specific parameters to define the data structure.
| Parameter | Type | Description |
|---|---|---|
itemsize | size_t | The number of bytes per individual item (e.g., 4 for float32) |
vlen | size_t | The number of items per vector |
num_streams | size_t | The number of parallel streams to interleave/deinterleave |
Sources: include/gnuradio/cuda/vector_to_stream.h:32-33, include/gnuradio/cuda/vector_to_streams.h:32-33
Implementation Details
The C++ implementations (e.g., vector_to_stream_impl and vector_to_streams_impl) utilize the cuda_block helper to manage GPU memory pointers. In the case of multi-stream blocks, the implementation maintains an array of device pointers to manage the various input or output ports.
class vector_to_streams_impl : public vector_to_streams, public cuda_block
{
private:
size_t d_itemsize;
size_t d_num_streams;
void** d_output_ptrs_dev; // Array of pointers on device
// ...
};
Sources: lib/vector_to_streams_impl.h:15-24, lib/vector_to_stream_impl.h:15-21
Data Flow for Multi-Stream Interleaving
The streams_to_vector block (Interleave) and vector_to_streams block (Deinterleave) facilitate complex data routing on the GPU.
This diagram represents the logical mapping of ports for interleaving and deinterleaving operations.
Sources: python/cuda/qa_stream_operators.py:46-60, python/cuda/qa_stream_operators.py:84-105
Usage in GPU Pipelines
These converters are frequently used to bridge single-threaded stream processing with parallelized vector processing.
Stream-Vector Chains
Chains can be constructed where data is repeatedly converted between streams and vectors to support different algorithmic requirements (e.g., FFTs requiring vectors vs. filters requiring streams). The gr-cuda framework handles the implicit copies between host and device if the pipeline transitions between CPU and GPU blocks.
# Example: Stream -> Vector -> Stream on GPU
s2v = cuda.stream_to_vector(4, vlen)
v2s = cuda.vector_to_stream(4, vlen)
self.tb.connect(src, s2v, v2s, snk)
Sources: python/cuda/qa_stream_operators.py:27-44, python/cuda/qa_stream_operators.py:107-124
Mixed Parallel Paths
Complex routing allows for splitting a vectored stream into individual parallel streams, processing them independently, and then re-interleaving them back into a single vector.
Sequence of data transformation in a mixed parallel processing chain.
Summary
The Stream and Vector Data Converters provide the "glue" logic for GPU-accelerated flowgraphs. By implementing stream_to_vector, vector_to_stream, and their multi-stream counterparts (streams_to_vector, vector_to_streams), gr-cuda enables flexible data reorganization. These blocks ensure that data is presented to subsequent GPU kernels in the required dimensionality and interleaved format, maintaining high throughput by minimizing CPU intervention during structural data changes.
Sources: python/cuda/qa_stream_operators.py:152-180, lib/vector_to_streams_impl.h