Add streaming filter support for conv1d, resample_poly, channelize_poly - #1209
Conversation
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>
Greptile SummaryThis PR adds
Confidence Score: 5/5Safe to merge. The streaming wrappers are purely additive and the windowed one-shot changes are backward-compatible (offset defaults to 0). All changed kernels default to prior behavior when out_elem_offset == 0. The streaming wrappers are purely additive and the windowed one-shot changes are backward-compatible. All kernel modifications are mechanical index shifts that leave the zero-offset case identical to the pre-PR behavior. The new tests cover windowed one-shot equivalence for every kernel dispatch variant, multiple segment schedules, short-stream edge cases, and host executors. The only findings are style-level: a duplicated helper function and a structural asymmetry between two streaming classes. No files require special attention for correctness. Reviewers interested in the alignment math may want to check the channelize_plan and resample_plan helper functions in the streaming headers. Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant StreamObj as Conv1DStream / ResamplePolyStream / ChannelizePolyStream
participant RetainBuf as Retain Buffer (ping-pong)
participant OneShot as One-shot Transform
User->>StreamObj: "make_*_stream(filter, params, exec)"
StreamObj->>RetainBuf: allocate 2xhistory_len (zeros)
StreamObj->>OneShot: materialize filter once
loop for each segment
User->>StreamObj: feed(new_samples, out_buf)
StreamObj->>StreamObj: compute plan (lo, cnt) from sizes only
StreamObj->>StreamObj: validate out_buf before lifecycle
StreamObj->>RetainBuf: read cur_retain (half A)
StreamObj->>OneShot: "one-shot([retain|new], out_elem_offset=lo, cnt)"
OneShot-->>User: cnt outputs written to out_buf[0:cnt]
StreamObj->>RetainBuf: write next_retain (half B, disjoint)
StreamObj->>StreamObj: flip ping-pong, update retain_len
StreamObj-->>User: return cnt
end
User->>StreamObj: flush(out_buf)
StreamObj->>RetainBuf: read cur_retain (final tail)
StreamObj->>OneShot: "one-shot(retain, out_elem_offset=lo, cnt)"
OneShot-->>User: trailing outputs written to out_buf[0:cnt]
StreamObj-->>User: "return cnt, mark flushed=true"
Reviews (2): Last reviewed commit: "Return count rather than slice from feed..." | Re-trigger Greptile |
|
/build |
MatX does not support 0-sized slices, but there are some cases in which feed()/flush() return no new samples. Rather than return a slice of the user-provided output, instead return the count of newly generated output samples. The user then creates their own slice, or otherwise consumes the output, if count > 0. Signed-off-by: Thomas Benson <tbenson@nvidia.com>
|
The initial version of this PR returned a slice of the user-provided output tensor from the feed()/flush() methods. There are cases in which there are zero new output samples, but MatX does not allow for zero-sized slices, so that approach failed in such cases. The API has been updated so that feed()/flush() instead return the count of output samples that have been written to the user-provided output tensor/operator. The user can then slice (if count > 0) or otherwise consume as needed. |
|
/build |
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.