dsp: align iir and iir_int, add iir micro benches
This commit is contained in:
parent
8408bc5811
commit
47089c267c
|
@ -15,7 +15,7 @@ ndarray = "0.14"
|
||||||
ndarray-stats = "0.4"
|
ndarray-stats = "0.4"
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "trig"
|
name = "micro"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use core::f32::consts::PI;
|
use core::f32::consts::PI;
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
use dsp::{atan2, cossin, pll::PLL, rpll::RPLL};
|
use dsp::{atan2, cossin};
|
||||||
|
use dsp::{iir, iir_int};
|
||||||
|
use dsp::{pll::PLL, rpll::RPLL};
|
||||||
|
|
||||||
fn atan2_bench(c: &mut Criterion) {
|
fn atan2_bench(c: &mut Criterion) {
|
||||||
let xi = (10 << 16) as i32;
|
let xi = (10 << 16) as i32;
|
||||||
|
@ -46,6 +48,23 @@ fn pll_bench(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn iir_int_bench(c: &mut Criterion) {
|
||||||
|
let dut = iir_int::IIR::default();
|
||||||
|
let mut xy = iir_int::IIRState::default();
|
||||||
|
c.bench_function("int_iir::IIR::update(s, x)", |b| {
|
||||||
|
b.iter(|| dut.update(&mut xy, black_box(0x2832)))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iir_bench(c: &mut Criterion) {
|
||||||
|
let dut = iir::IIR::default();
|
||||||
|
let mut xy = iir::IIRState::default();
|
||||||
|
c.bench_function("int::IIR::update(s, x)", |b| {
|
||||||
|
b.iter(|| dut.update(&mut xy, black_box(0.32241)))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
criterion_group!(trig, atan2_bench, cossin_bench);
|
criterion_group!(trig, atan2_bench, cossin_bench);
|
||||||
criterion_group!(pll, rpll_bench, pll_bench);
|
criterion_group!(pll, rpll_bench, pll_bench);
|
||||||
criterion_main!(trig, pll);
|
criterion_group!(iir, iir_int_bench, iir_bench);
|
||||||
|
criterion_main!(trig, pll, iir);
|
||||||
|
|
|
@ -11,7 +11,8 @@ use core::f32;
|
||||||
/// To represent the IIR coefficients, this contains the feed-forward
|
/// To represent the IIR coefficients, this contains the feed-forward
|
||||||
/// coefficients (b0, b1, b2) followd by the negated feed-back coefficients
|
/// coefficients (b0, b1, b2) followd by the negated feed-back coefficients
|
||||||
/// (-a1, -a2), all five normalized such that a0 = 1.
|
/// (-a1, -a2), all five normalized such that a0 = 1.
|
||||||
pub type IIRState = [f32; 5];
|
#[derive(Copy, Clone, Default, Deserialize, Serialize)]
|
||||||
|
pub struct IIRState(pub [f32; 5]);
|
||||||
|
|
||||||
/// IIR configuration.
|
/// IIR configuration.
|
||||||
///
|
///
|
||||||
|
@ -38,7 +39,7 @@ pub type IIRState = [f32; 5];
|
||||||
/// Therefore it can trivially implement bump-less transfer.
|
/// Therefore it can trivially implement bump-less transfer.
|
||||||
/// * Cascading multiple IIR filters allows stable and robust
|
/// * Cascading multiple IIR filters allows stable and robust
|
||||||
/// implementation of transfer functions beyond bequadratic terms.
|
/// implementation of transfer functions beyond bequadratic terms.
|
||||||
#[derive(Copy, Clone, Deserialize, Serialize)]
|
#[derive(Copy, Clone, Default, Deserialize, Serialize)]
|
||||||
pub struct IIR {
|
pub struct IIR {
|
||||||
pub ba: IIRState,
|
pub ba: IIRState,
|
||||||
pub y_offset: f32,
|
pub y_offset: f32,
|
||||||
|
@ -74,13 +75,13 @@ impl IIR {
|
||||||
}
|
}
|
||||||
(a1, b0, b1)
|
(a1, b0, b1)
|
||||||
};
|
};
|
||||||
self.ba.copy_from_slice(&[b0, b1, 0., a1, 0.]);
|
self.ba.0.copy_from_slice(&[b0, b1, 0., a1, 0.]);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the overall (DC feed-forward) gain.
|
/// Compute the overall (DC feed-forward) gain.
|
||||||
pub fn get_k(&self) -> f32 {
|
pub fn get_k(&self) -> f32 {
|
||||||
self.ba[..3].iter().sum()
|
self.ba.0[..3].iter().sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute input-referred (`x`) offset from output (`y`) offset.
|
/// Compute input-referred (`x`) offset from output (`y`) offset.
|
||||||
|
@ -108,21 +109,21 @@ impl IIR {
|
||||||
/// * `xy` - Current filter state.
|
/// * `xy` - Current filter state.
|
||||||
/// * `x0` - New input.
|
/// * `x0` - New input.
|
||||||
pub fn update(&self, xy: &mut IIRState, x0: f32) -> f32 {
|
pub fn update(&self, xy: &mut IIRState, x0: f32) -> f32 {
|
||||||
let n = self.ba.len();
|
let n = self.ba.0.len();
|
||||||
debug_assert!(xy.len() == n);
|
debug_assert!(xy.0.len() == n);
|
||||||
// `xy` contains x0 x1 y0 y1 y2
|
// `xy` contains x0 x1 y0 y1 y2
|
||||||
// Increment time x1 x2 y1 y2 y3
|
// Increment time x1 x2 y1 y2 y3
|
||||||
// Shift x1 x1 x2 y1 y2
|
// Shift x1 x1 x2 y1 y2
|
||||||
// This unrolls better than xy.rotate_right(1)
|
// This unrolls better than xy.rotate_right(1)
|
||||||
xy.copy_within(0..n - 1, 1);
|
xy.0.copy_within(0..n - 1, 1);
|
||||||
// Store x0 x0 x1 x2 y1 y2
|
// Store x0 x0 x1 x2 y1 y2
|
||||||
xy[0] = x0;
|
xy.0[0] = x0;
|
||||||
// Compute y0 by multiply-accumulate
|
// Compute y0 by multiply-accumulate
|
||||||
let y0 = macc(self.y_offset, xy, &self.ba);
|
let y0 = macc(self.y_offset, &xy.0, &self.ba.0);
|
||||||
// Limit y0
|
// Limit y0
|
||||||
let y0 = max(self.y_min, min(self.y_max, y0));
|
let y0 = max(self.y_min, min(self.y_max, y0));
|
||||||
// Store y0 x0 x1 y0 y1 y2
|
// Store y0 x0 x1 y0 y1 y2
|
||||||
xy[n / 2] = y0;
|
xy.0[n / 2] = y0;
|
||||||
y0
|
y0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,9 +34,9 @@ const APP: () = {
|
||||||
net_interface: hardware::Ethernet,
|
net_interface: hardware::Ethernet,
|
||||||
|
|
||||||
// Format: iir_state[ch][cascade-no][coeff]
|
// Format: iir_state[ch][cascade-no][coeff]
|
||||||
#[init([[[0.; 5]; IIR_CASCADE_LENGTH]; 2])]
|
#[init([[iir::IIRState([0.; 5]); IIR_CASCADE_LENGTH]; 2])]
|
||||||
iir_state: [[iir::IIRState; IIR_CASCADE_LENGTH]; 2],
|
iir_state: [[iir::IIRState; IIR_CASCADE_LENGTH]; 2],
|
||||||
#[init([[iir::IIR { ba: [1., 0., 0., 0., 0.], y_offset: 0., y_min: -SCALE - 1., y_max: SCALE }; IIR_CASCADE_LENGTH]; 2])]
|
#[init([[iir::IIR { ba: iir::IIRState([1., 0., 0., 0., 0.]), y_offset: 0., y_min: -SCALE - 1., y_max: SCALE }; IIR_CASCADE_LENGTH]; 2])]
|
||||||
iir_ch: [[iir::IIR; IIR_CASCADE_LENGTH]; 2],
|
iir_ch: [[iir::IIR; IIR_CASCADE_LENGTH]; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,10 +159,10 @@ const APP: () = {
|
||||||
let state = c.resources.iir_state.lock(|iir_state|
|
let state = c.resources.iir_state.lock(|iir_state|
|
||||||
server::Status {
|
server::Status {
|
||||||
t: time,
|
t: time,
|
||||||
x0: iir_state[0][0][0],
|
x0: iir_state[0][0].0[0],
|
||||||
y0: iir_state[0][0][2],
|
y0: iir_state[0][0].0[2],
|
||||||
x1: iir_state[1][0][0],
|
x1: iir_state[1][0].0[0],
|
||||||
y1: iir_state[1][0][2],
|
y1: iir_state[1][0].0[2],
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok::<server::Status, ()>(state)
|
Ok::<server::Status, ()>(state)
|
||||||
|
@ -171,10 +171,10 @@ const APP: () = {
|
||||||
"stabilizer/iir_b/state": (|| { let state = c.resources.iir_state.lock(|iir_state|
|
"stabilizer/iir_b/state": (|| { let state = c.resources.iir_state.lock(|iir_state|
|
||||||
server::Status {
|
server::Status {
|
||||||
t: time,
|
t: time,
|
||||||
x0: iir_state[0][IIR_CASCADE_LENGTH-1][0],
|
x0: iir_state[0][IIR_CASCADE_LENGTH-1].0[0],
|
||||||
y0: iir_state[0][IIR_CASCADE_LENGTH-1][2],
|
y0: iir_state[0][IIR_CASCADE_LENGTH-1].0[2],
|
||||||
x1: iir_state[1][IIR_CASCADE_LENGTH-1][0],
|
x1: iir_state[1][IIR_CASCADE_LENGTH-1].0[0],
|
||||||
y1: iir_state[1][IIR_CASCADE_LENGTH-1][2],
|
y1: iir_state[1][IIR_CASCADE_LENGTH-1].0[2],
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok::<server::Status, ()>(state)
|
Ok::<server::Status, ()>(state)
|
||||||
|
|
|
@ -38,9 +38,9 @@ const APP: () = {
|
||||||
net_interface: hardware::Ethernet,
|
net_interface: hardware::Ethernet,
|
||||||
|
|
||||||
// Format: iir_state[ch][cascade-no][coeff]
|
// Format: iir_state[ch][cascade-no][coeff]
|
||||||
#[init([[[0.; 5]; IIR_CASCADE_LENGTH]; 2])]
|
#[init([[iir::IIRState([0.; 5]); IIR_CASCADE_LENGTH]; 2])]
|
||||||
iir_state: [[iir::IIRState; IIR_CASCADE_LENGTH]; 2],
|
iir_state: [[iir::IIRState; IIR_CASCADE_LENGTH]; 2],
|
||||||
#[init([[iir::IIR { ba: [1., 0., 0., 0., 0.], y_offset: 0., y_min: -SCALE - 1., y_max: SCALE }; IIR_CASCADE_LENGTH]; 2])]
|
#[init([[iir::IIR { ba: iir::IIRState([1., 0., 0., 0., 0.]), y_offset: 0., y_min: -SCALE - 1., y_max: SCALE }; IIR_CASCADE_LENGTH]; 2])]
|
||||||
iir_ch: [[iir::IIR; IIR_CASCADE_LENGTH]; 2],
|
iir_ch: [[iir::IIR; IIR_CASCADE_LENGTH]; 2],
|
||||||
|
|
||||||
timestamper: InputStamper,
|
timestamper: InputStamper,
|
||||||
|
@ -216,10 +216,10 @@ const APP: () = {
|
||||||
let state = c.resources.iir_state.lock(|iir_state|
|
let state = c.resources.iir_state.lock(|iir_state|
|
||||||
server::Status {
|
server::Status {
|
||||||
t: time,
|
t: time,
|
||||||
x0: iir_state[0][0][0],
|
x0: iir_state[0][0].0[0],
|
||||||
y0: iir_state[0][0][2],
|
y0: iir_state[0][0].0[2],
|
||||||
x1: iir_state[1][0][0],
|
x1: iir_state[1][0].0[0],
|
||||||
y1: iir_state[1][0][2],
|
y1: iir_state[1][0].0[2],
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok::<server::Status, ()>(state)
|
Ok::<server::Status, ()>(state)
|
||||||
|
@ -228,10 +228,10 @@ const APP: () = {
|
||||||
"stabilizer/iir_b/state": (|| { let state = c.resources.iir_state.lock(|iir_state|
|
"stabilizer/iir_b/state": (|| { let state = c.resources.iir_state.lock(|iir_state|
|
||||||
server::Status {
|
server::Status {
|
||||||
t: time,
|
t: time,
|
||||||
x0: iir_state[0][IIR_CASCADE_LENGTH-1][0],
|
x0: iir_state[0][IIR_CASCADE_LENGTH-1].0[0],
|
||||||
y0: iir_state[0][IIR_CASCADE_LENGTH-1][2],
|
y0: iir_state[0][IIR_CASCADE_LENGTH-1].0[2],
|
||||||
x1: iir_state[1][IIR_CASCADE_LENGTH-1][0],
|
x1: iir_state[1][IIR_CASCADE_LENGTH-1].0[0],
|
||||||
y1: iir_state[1][IIR_CASCADE_LENGTH-1][2],
|
y1: iir_state[1][IIR_CASCADE_LENGTH-1].0[2],
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok::<server::Status, ()>(state)
|
Ok::<server::Status, ()>(state)
|
||||||
|
|
Loading…
Reference in New Issue