-
Notifications
You must be signed in to change notification settings - Fork 6
SIMD deinterleave #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # AGENTS.md - Hub for fsdr-blocks | ||
|
|
||
| Building blocks for FutureSDR signal processing library for SDR and real-time DSP. | ||
|
|
||
| ## Tech Stack | ||
| - **Language:** Rust (Edition 2024, **Nightly channel**) | ||
| - **Core Library:** [FutureSDR](https://www.futuresdr.org) | ||
| - **Acceleration:** Explicit SIMD via `std::simd` (portable SIMD) | ||
| - **Serialization:** Serde, custom PMT (Polymorphic Types) | ||
| - **Testing:** Cargo test, QuickCheck, Criterion (benchmarks) | ||
|
|
||
| ## Critical Commands | ||
| - **Install:** `cargo build` | ||
| - **Lint:** `./check.sh` (Runs fmt, clippy, and tests with all features) | ||
| - **Test:** `cargo test --all-features` | ||
| - **Bench:** `cargo bench --all-features` | ||
|
|
||
| ## Documentation Index | ||
| - [Architecture](agent_docs/architecture.md): **Trigger:** Designing new blocks or understanding flowgraph connectivity. | ||
| - [Conventions](agent_docs/conventions.md): **Trigger:** Before writing any code to ensure alignment with Rust 2024 and FutureSDR idioms. | ||
| - [SDR & DSP](agent_docs/sdr_dsp.md): **Trigger:** Modifying signal processing logic, gain control, or frequency shifts. | ||
| - [SigMF](agent_docs/sigmf.md): **Trigger:** Working with Signal Metadata Format (SigMF) recordings or collections. | ||
|
|
||
| ## Verification Loop | ||
| You MUST run `./check.sh` and ensure all tests pass before declaring a task "done." | ||
| Always verify that your changes didn't break conditional feature flags (`crossbeam`, `async-channel`, `cw`). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| # Architecture - fsdr-blocks | ||
|
|
||
| This project follows the **Flowgraph/Block** paradigm provided by FutureSDR. | ||
|
|
||
| ## Core Concepts | ||
| - **Blocks:** The fundamental units of processing. Defined using `#[derive(Block)]`. | ||
| - **Flowgraph:** A directed acyclic graph (usually) where blocks are nodes and streams/messages are edges. | ||
| - **Kernels:** The execution logic of a block. Most blocks in this repository are CPU-based and implement the `Kernel` trait. | ||
|
|
||
| ## Data Movement | ||
| - **Streams:** High-throughput data (e.g., IQ samples) passed via `CpuBufferReader`/`CpuBufferWriter`. | ||
| - **Messages:** Asynchronous control signals or metadata passed as `Pmt` (Polymorphic Types). | ||
|
|
||
| ## Dependency on FutureSDR | ||
| This project is tightly coupled with `futuresdr`. It uses a local path dependency in `Cargo.toml` by default (`../FutureSDR`), which indicates it is often developed alongside the core library. | ||
|
|
||
| ## Block Types | ||
| - **Sources/Sinks:** Handle I/O (e.g., `StdinSink`, `SigmfSource`). | ||
| - **Processing Blocks:** Transform data (e.g., `Agc`, `FreqShift`). | ||
| - **Adapters:** Connect different async runtimes or channel types (e.g., `CrossbeamSink`). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| # Conventions - fsdr-blocks | ||
|
|
||
| ## Rust Standards | ||
| - **Edition:** 2024. Use modern idioms (e.g., `async fn` in traits, let-else). | ||
| - **Formatting:** Strictly adhere to `cargo fmt`. | ||
|
|
||
| ## Block Implementation Boilerplate | ||
| Every block should typically include: | ||
| 1. **Struct Definition:** Use `#[derive(Block)]` and specify `#[message_inputs(...)]` if applicable. | ||
| 2. **Implementation:** A `new` method and message handler methods (returning `Result<Pmt>`). | ||
| 3. **Kernel Trait:** Implement `async fn work` to handle the data processing loop. | ||
| 4. **Builder Pattern:** Use a `BlockBuilder` struct for complex configuration (see `src/agc.rs`). | ||
|
|
||
| ## Performance Acceleration | ||
| For blocks in hot loops (AGC, Frequency Shift, Deinterleave), prefer explicit SIMD over compiler-dependent autovectorization: | ||
| 1. **Feature Flags:** Ensure `portable_simd` and `specialization` are enabled in `src/lib.rs`. | ||
| 2. **Specialization Pattern:** Define a `*Supported` trait (e.g., `DeinterleaveSupported`) with a `default` scalar implementation and specialized SIMD implementations for `f32`, `u8`, `i8`, `i16`. | ||
| 3. **Macro Reuse:** Use macros to implement SIMD logic across different types to avoid code duplication. | ||
| 4. **Benchmarking:** Every accelerated block MUST have a corresponding `Criterion` benchmark in `benches/`. | ||
|
|
||
| ## Error Handling | ||
| - Use `futuresdr::anyhow::Result` for block operations. | ||
| - Prefer `Context` from `anyhow` for descriptive error messages in I/O operations. | ||
|
|
||
| ## Feature Management | ||
| - Use `#[cfg(feature = "...")]` for blocks that depend on optional crates like `crossbeam-channel` or `async-channel`. | ||
| - Always test with `--all-features` to ensure no regressions in optional components. | ||
|
|
||
| ## Testing | ||
| - **Unit Tests:** Located in `tests/`. | ||
| - **Property-Based Testing:** Use `quickcheck` for robust validation of DSP algorithms. | ||
| - **Benchmarks:** Located in `benches/`, using `Criterion`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # SDR & DSP - fsdr-blocks | ||
|
|
||
| ## Signal Processing Idioms | ||
| - **Complex Numbers:** Use `num_complex::Complex32` (or generic `T: ComplexFloat`). | ||
| - **Buffers:** Always use `input.slice()` and `output.slice()` in the `work` function. | ||
| - **Consumption/Production:** Explicitly call `input.consume(n)` and `output.produce(n)` after processing. | ||
|
|
||
| ## Key Blocks | ||
| - **AGC (Automatic Gain Control):** Implements a feedback loop to maintain target power. See `src/agc.rs`. | ||
| - **FreqShift:** Performs digital down-conversion/up-conversion. See `src/math/freq_shift.rs`. | ||
| - **Type Converters:** Crucial for translating between raw bytes and SDR-specific types. | ||
|
|
||
| ## Math Operations | ||
| - **Prefer Explicit SIMD:** Use `std::simd` and specialization (see `DeinterleaveSupported`) for performance-critical blocks in hot loops. This avoids dependency on brittle compiler autovectorization. | ||
| - **Precision:** Be mindful of floating-point precision and squelch thresholds. | ||
| - **Error Accumulation:** Periodically re-calculate phase in recurrence relations to prevent drift (e.g., in `FreqShift`). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # SigMF - fsdr-blocks | ||
|
|
||
| ## Overview | ||
| The `sigmf` crate (in `crates/sigmf`) provides a Rust implementation of the [Signal Metadata Format](https://github.com/sigmf/SigMF). | ||
|
|
||
| ## Structure | ||
| - **Global:** Top-level metadata about the recording. | ||
| - **Captures:** Segment-specific metadata (sample rate, frequency). | ||
| - **Annotations:** Time/frequency-indexed labels. | ||
|
|
||
| ## Usage in fsdr-blocks | ||
| - `SigmfSource`: Reads `.sigmf-meta` and `.sigmf-data` files into a FutureSDR flowgraph. | ||
| - `SigmfSink`: Records flowgraph data into SigMF-compliant files. | ||
|
|
||
| ## Extensions | ||
| Supports SigMF extensions (e.g., `AntennaExtension`). New extensions should be added as modules in `crates/sigmf/src/`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| use criterion::{Criterion, Throughput, criterion_group, criterion_main}; | ||
| use fsdr_blocks::stream::Deinterleave; | ||
| use futuresdr::runtime::mocker::{Mocker, Reader, Writer}; | ||
| use rand::RngExt; | ||
|
|
||
| pub fn deinterleave_f32(c: &mut Criterion) { | ||
| let n_samp = 8192; | ||
| let mut rng = rand::rng(); | ||
| let input: Vec<f32> = (0..n_samp).map(|_| rng.random()).collect(); | ||
|
|
||
| let mut group = c.benchmark_group("deinterleave"); | ||
| group.throughput(Throughput::Elements(n_samp as u64)); | ||
|
|
||
| group.bench_function("deinterleave_f32", |b| { | ||
| b.iter(|| { | ||
| let block: Deinterleave<f32, Reader<f32>, Writer<f32>, Writer<f32>> = | ||
| Deinterleave::new(); | ||
| let mut mocker = Mocker::new(block); | ||
| mocker.input().set(input.clone()); | ||
| mocker.run(); | ||
| }); | ||
| }); | ||
|
|
||
| group.finish(); | ||
| } | ||
|
|
||
| criterion_group!(benches, deinterleave_f32); | ||
| criterion_main!(benches); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you tested, if instead of implementing deinterleave using simd isntruction, this can also be achieved using autovectorization?
AI generated code is usually very good, if reviewd correctly. Still, allowing your agent to check, if the code generated by a non-simd implementation is being autovectorized, might keep the code more readable also for humans.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I did try autovectorization but was not able to achieve this portably. So after several trials, I went to add this explicitly. But if you have hints, maybe I can try again.