Skip to content

Commit d9e618e

Browse files
authored
Add streaming filter support for conv1d, resample_poly, channelize_poly (#1209)
* Add streaming filter support for conv1d, resample_poly, channelize_poly Add Conv1DStream, ResamplePolyStream, and ChannelizePolyStream objects that filter arbitrarily long signals delivered in segments. Segments of any size are supplied via feed() and a final flush() emits the trailing outputs and ends the stream. The concatenated outputs match the corresponding one-shot transform. Objects are created with the make_*_stream() factories and support CUDA and host executors. Each object retains only a small history buffer between calls, and feed()/flush() write into a caller-provided output buffer sized once via max_output(), so no allocation occurs during streaming. conv1d supports FULL/SAME/VALID modes. To support the internal windowed one-shot calls, the resample_poly and channelize_poly transforms and kernels gain output-window offset parameters. See examples/streaming.cu and the API Reference section Signal and Image Processing / Streaming for usage and per-transform caveats. Tests cover one-shot equivalence across filter/segment configurations, varying segment schedules, end-of-stream semantics, and host executors. Signed-off-by: Thomas Benson <tbenson@nvidia.com>
1 parent 8f27d7d commit d9e618e

25 files changed

Lines changed: 3953 additions & 270 deletions

docs_input/api/signalimage/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ Signal and Image Processing
1010
filtering/index.rst
1111
general/index.rst
1212
radar/index.rst
13+
streaming/index.rst
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
.. _make_channelize_poly_stream_func:
2+
3+
make_channelize_poly_stream
4+
===========================
5+
6+
Streaming polyphase channelizer: channelize a signal delivered in segments,
7+
equivalent to a one-shot :ref:`channelize_poly <channelize_poly_func>` over
8+
the concatenated stream
9+
10+
.. versionadded:: 1.1.0
11+
12+
.. doxygenstruct:: matx::ChannelizePolyStreamParams
13+
:members:
14+
15+
.. doxygenfunction:: matx::make_channelize_poly_stream
16+
17+
.. doxygenclass:: matx::ChannelizePolyStream
18+
:members:
19+
20+
Examples
21+
~~~~~~~~
22+
23+
.. literalinclude:: ../../../../examples/streaming.cu
24+
:language: cpp
25+
:start-after: example-begin channelize_poly_stream-1
26+
:end-before: example-end channelize_poly_stream-1
27+
:dedent:
28+
29+
.. literalinclude:: ../../../../examples/streaming.cu
30+
:language: cpp
31+
:start-after: example-begin channelize_poly_stream-2
32+
:end-before: example-end channelize_poly_stream-2
33+
:dedent:
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
.. _make_conv1d_stream_func:
2+
3+
make_conv1d_stream
4+
==================
5+
6+
Streaming 1D convolution: filter a signal delivered in segments. The concatenated
7+
output equals a one-shot :ref:`conv1d <conv1d_func>` over the whole stream when the
8+
total signal length is at least the filter length. For shorter signals one-shot
9+
conv1d swaps the operand roles, while the streaming object keeps the signal and
10+
filter roles fixed and returns the input-aligned result. FULL mode is
11+
role-symmetric and matches for any length. The convolution uses the direct
12+
(time-domain) method, which limits the filter to 1024 taps.
13+
14+
.. versionadded:: 1.1.0
15+
16+
.. doxygenstruct:: matx::Conv1DStreamParams
17+
:members:
18+
19+
.. doxygenfunction:: matx::make_conv1d_stream
20+
21+
.. doxygenclass:: matx::Conv1DStream
22+
:members:
23+
24+
Examples
25+
~~~~~~~~
26+
27+
.. literalinclude:: ../../../../examples/streaming.cu
28+
:language: cpp
29+
:start-after: example-begin conv1d_stream-1
30+
:end-before: example-end conv1d_stream-1
31+
:dedent:
32+
33+
.. literalinclude:: ../../../../examples/streaming.cu
34+
:language: cpp
35+
:start-after: example-begin conv1d_stream-2
36+
:end-before: example-end conv1d_stream-2
37+
:dedent:
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
.. _streaming:
2+
3+
Streaming
4+
#########
5+
6+
Streaming objects process arbitrarily long signals delivered in segments. An
7+
object is constructed once via its ``make_*_stream()`` factory, then fed
8+
segments of any (possibly varying) size with ``feed()``. A final ``flush()`` is called
9+
at the end of the stream to emit any trailing outputs. ``flush()`` ends the stream:
10+
further ``flush()`` calls return 0, and ``feed()`` throws until
11+
``reset()`` starts a new stream. The concatenation of the
12+
produced outputs equals a single one-shot call of the corresponding transform
13+
over the whole signal, with a few caveats as documented for each streaming object.
14+
Each object owns only a small history buffer that scales with the filter and some
15+
object parameters (e.g., the downsampling factor for ``resample_poly``). No object-owned
16+
allocation scales directly with the segment size.
17+
All work runs asynchronously on the executor bound at construction.
18+
19+
The canonical pattern sizes one reusable output buffer with
20+
``max_output(largest_input_segment_size)`` and passes it to every ``feed()`` and
21+
``flush()`` call. Each call writes its outputs to the front of that buffer and
22+
returns the number written (which may be 0). Consume the produced region
23+
``slice(out, {0}, {count})`` before reusing the buffer. Note that zero-sized slices
24+
are not valid, so check ``count > 0`` before creating and using the slice.
25+
This pattern prevents any dynamic memory allocation for the outputs during the streaming operation.
26+
See ``examples/streaming.cu`` for complete programs.
27+
28+
.. toctree::
29+
:maxdepth: 1
30+
:glob:
31+
32+
*
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
.. _make_resample_poly_stream_func:
2+
3+
make_resample_poly_stream
4+
=========================
5+
6+
Streaming polyphase resampler: resample a signal delivered in segments,
7+
equivalent to a one-shot :ref:`resample_poly <resample_poly_func>` over the
8+
concatenated stream
9+
10+
.. versionadded:: 1.1.0
11+
12+
.. doxygenstruct:: matx::ResamplePolyStreamParams
13+
:members:
14+
15+
.. doxygenfunction:: matx::make_resample_poly_stream
16+
17+
.. doxygenclass:: matx::ResamplePolyStream
18+
:members:
19+
20+
Examples
21+
~~~~~~~~
22+
23+
.. literalinclude:: ../../../../examples/streaming.cu
24+
:language: cpp
25+
:start-after: example-begin resample_poly_stream-1
26+
:end-before: example-end resample_poly_stream-1
27+
:dedent:
28+
29+
.. literalinclude:: ../../../../examples/streaming.cu
30+
:language: cpp
31+
:start-after: example-begin resample_poly_stream-2
32+
:end-before: example-end resample_poly_stream-2
33+
:dedent:

docs_input/executor_compatibility.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ fused JIT expression; non-JIT CUDA execution through cudaExecutor remains availa
140140
"log2", "|yes|", "|yes|", "|yes|", "Element-wise expression."
141141
"logspace", "|yes|", "|yes|", "|yes|", "Generator expression."
142142
"lu", "|yes|", "|yes|", "|yes|", "Host support requires the CPU solver backend. CUDAJITExecutor supports cuSolverDx-backed lazy projections for supported types and shapes."
143+
"make_channelize_poly_stream", "|yes|", "|yes|", "|no|", "Streaming (segmented) polyphase channelizer object; feeds segments through the one-shot channelize_poly over a retained history. Host and CUDA executors; the streaming object is a stateful driver, not a JIT-fusable expression."
144+
"make_conv1d_stream", "|yes|", "|yes|", "|no|", "Streaming (segmented) 1D convolution object built on the direct conv1d; host and CUDA executors. The direct method limits the filter to 1024 taps. The streaming object is a stateful driver, not a JIT-fusable expression."
145+
"make_resample_poly_stream", "|yes|", "|yes|", "|no|", "Streaming (segmented) polyphase resampler object; feeds segments through the one-shot resample_poly over a retained history. Host and CUDA executors; the streaming object is a stateful driver, not a JIT-fusable expression."
143146
"matmul", "|yes|", "|yes|", "|yes|", "Host support requires the CPU BLAS backend and supported floating or complex types. CUDAJITExecutor support uses cuBLASDx through MathDx for supported runtime shapes, precisions, layouts, and block-size intersections."
144147
"matrix_norm", "|partial|", "|yes|", "|no|", "Reduction transform; host execution is available but reductions are not generally parallelized across host threads."
145148
"matvec", "|yes|", "|yes|", "|yes|", "Host support requires the CPU BLAS backend and supported floating or complex types. CUDAJITExecutor support follows cuBLASDx matmul constraints."

examples/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ set(examples
2121
svd_power
2222
qr
2323
black_scholes
24-
print_styles)
24+
print_styles
25+
streaming)
2526

2627

2728

0 commit comments

Comments
 (0)