Skip to main content

perf_comparison/
perf_comparison.rs

1use embedded_dsp::*;
2use std::time::Instant;
3
4fn main() {
5    println!(
6        "========================================================================================="
7    );
8    println!(
9        "                  embedded-dsp vs libm Performance Benchmark Comparison                  "
10    );
11    println!(
12        "========================================================================================="
13    );
14    println!();
15
16    const ITERATIONS: usize = 1_000_000;
17    const VECTOR_SIZE: usize = 256;
18
19    // -----------------------------------------------------------------------------------------
20    // 1. Scalar Trigonometric Sine Performance (1,000,000 operations)
21    // -----------------------------------------------------------------------------------------
22    println!(
23        "--- 1. Scalar Math Operations ({} iterations) ---",
24        ITERATIONS
25    );
26
27    // libm::sinf
28    let start = Instant::now();
29    let mut sum_libm = 0.0f32;
30    for i in 0..ITERATIONS {
31        let x = (i % 360) as f32 * (std::f32::consts::PI / 180.0);
32        sum_libm += libm::sinf(x);
33    }
34    let duration_libm_sin = start.elapsed();
35
36    // embedded-dsp f32 sin
37    let start = Instant::now();
38    let mut sum_dsp_f32 = 0.0f32;
39    for i in 0..ITERATIONS {
40        let x = (i % 360) as f32 * (std::f32::consts::PI / 180.0);
41        sum_dsp_f32 += sin_f32(x);
42    }
43    let duration_dsp_f32_sin = start.elapsed();
44
45    // embedded-dsp q31 sin (Fixed Point Integer Math)
46    let start = Instant::now();
47    let mut sum_dsp_q31 = 0i32;
48    for i in 0..ITERATIONS {
49        let theta_q31 = ((i % 360) as i64 * 2147483648 / 360) as i32;
50        sum_dsp_q31 = sum_dsp_q31.wrapping_add(sin_q31(theta_q31));
51    }
52    let duration_dsp_q31_sin = start.elapsed();
53
54    println!(
55        "  • libm::sinf         : {:>9.2?}  (sum check: {:.2})",
56        duration_libm_sin, sum_libm
57    );
58    println!(
59        "  • embedded-dsp f32   : {:>9.2?}  (sum check: {:.2})",
60        duration_dsp_f32_sin, sum_dsp_f32
61    );
62    println!(
63        "  • embedded-dsp q31   : {:>9.2?}  (sum check: {})",
64        duration_dsp_q31_sin, sum_dsp_q31
65    );
66    println!();
67
68    // -----------------------------------------------------------------------------------------
69    // 2. Square Root Performance (1,000,000 operations)
70    // -----------------------------------------------------------------------------------------
71    println!(
72        "--- 2. Square Root Operations ({} iterations) ---",
73        ITERATIONS
74    );
75
76    // libm::sqrtf
77    let start = Instant::now();
78    let mut sum_libm_sqrt = 0.0f32;
79    for i in 1..=ITERATIONS {
80        sum_libm_sqrt += libm::sqrtf(i as f32);
81    }
82    let duration_libm_sqrt = start.elapsed();
83
84    // embedded-dsp sqrt_f32
85    let start = Instant::now();
86    let mut sum_dsp_sqrt_f32 = 0.0f32;
87    let mut out_f32 = 0.0f32;
88    for i in 1..=ITERATIONS {
89        sqrt_f32(i as f32, &mut out_f32);
90        sum_dsp_sqrt_f32 += out_f32;
91    }
92    let duration_dsp_sqrt_f32 = start.elapsed();
93
94    // embedded-dsp sqrt_q31 (Fixed-point)
95    let start = Instant::now();
96    let mut sum_dsp_sqrt_q31 = 0i32;
97    let mut out_q31 = 0i32;
98    for i in 1..=ITERATIONS {
99        let val_q31 = (i as i64 * 2147483647 / ITERATIONS as i64) as i32;
100        sqrt_q31(val_q31, &mut out_q31);
101        sum_dsp_sqrt_q31 = sum_dsp_sqrt_q31.wrapping_add(out_q31);
102    }
103    let duration_dsp_sqrt_q31 = start.elapsed();
104
105    println!(
106        "  • libm::sqrtf        : {:>9.2?}  (sum check: {:.2})",
107        duration_libm_sqrt, sum_libm_sqrt
108    );
109    println!(
110        "  • embedded-dsp f32   : {:>9.2?}  (sum check: {:.2})",
111        duration_dsp_sqrt_f32, sum_dsp_sqrt_f32
112    );
113    println!(
114        "  • embedded-dsp q31   : {:>9.2?}  (sum check: {})",
115        duration_dsp_sqrt_q31, sum_dsp_sqrt_q31
116    );
117    println!();
118
119    // -----------------------------------------------------------------------------------------
120    // 3. DSP Vector Dot Product (Vector size: 256, 100,000 iterations)
121    // -----------------------------------------------------------------------------------------
122    const VECTOR_ITERATIONS: usize = 100_000;
123    println!(
124        "--- 3. Vector Dot Product (Size: {}, {} iterations) ---",
125        VECTOR_SIZE, VECTOR_ITERATIONS
126    );
127
128    let src_a_f32 = vec![1.5f32; VECTOR_SIZE];
129    let src_b_f32 = vec![2.5f32; VECTOR_SIZE];
130
131    let src_a_q31 = vec![1000000i32; VECTOR_SIZE];
132    let src_b_q31 = vec![2000000i32; VECTOR_SIZE];
133
134    let src_a_q15 = vec![1000i16; VECTOR_SIZE];
135    let src_b_q15 = vec![2000i16; VECTOR_SIZE];
136
137    // f32 Dot Product
138    let start = Instant::now();
139    let mut dot_f32_sum = 0.0f32;
140    for _ in 0..VECTOR_ITERATIONS {
141        dot_f32_sum += dot_prod_f32(&src_a_f32, &src_b_f32);
142    }
143    let duration_dot_f32 = start.elapsed();
144
145    // q31 Dot Product
146    let start = Instant::now();
147    let mut dot_q31_sum = 0i64;
148    for _ in 0..VECTOR_ITERATIONS {
149        dot_q31_sum = dot_q31_sum.wrapping_add(dot_prod_q31(&src_a_q31, &src_b_q31));
150    }
151    let duration_dot_q31 = start.elapsed();
152
153    // q15 Dot Product
154    let start = Instant::now();
155    let mut dot_q15_sum = 0i64;
156    for _ in 0..VECTOR_ITERATIONS {
157        dot_q15_sum = dot_q15_sum.wrapping_add(dot_prod_q15(&src_a_q15, &src_b_q15));
158    }
159    let duration_dot_q15 = start.elapsed();
160
161    println!(
162        "  • dot_prod_f32       : {:>9.2?}  (sum check: {:.2})",
163        duration_dot_f32, dot_f32_sum
164    );
165    println!(
166        "  • dot_prod_q31       : {:>9.2?}  (sum check: {}, speedup vs f32: {:.2}x)",
167        duration_dot_q31,
168        dot_q31_sum,
169        duration_dot_f32.as_secs_f64() / duration_dot_q31.as_secs_f64()
170    );
171    println!(
172        "  • dot_prod_q15       : {:>9.2?}  (sum check: {}, speedup vs f32: {:.2}x)",
173        duration_dot_q15,
174        dot_q15_sum,
175        duration_dot_f32.as_secs_f64() / duration_dot_q15.as_secs_f64()
176    );
177    println!();
178
179    // -----------------------------------------------------------------------------------------
180    // 4. 256-Point Complex FFT (10,000 iterations)
181    // -----------------------------------------------------------------------------------------
182    const FFT_ITERATIONS: usize = 10_000;
183    println!(
184        "--- 4. 256-Point Complex FFT ({} iterations) ---",
185        FFT_ITERATIONS
186    );
187
188    let mut fft_data_f32 = vec![0.0f32; 512]; // 256 complex pairs
189    let mut fft_data_q31 = vec![0i32; 512];
190    let mut fft_data_q15 = vec![0i16; 512];
191
192    for i in 0..256 {
193        fft_data_f32[2 * i] = (i as f32).sin();
194        fft_data_q31[2 * i] = (i * 1000) as i32;
195        fft_data_q15[2 * i] = (i * 100) as i16;
196    }
197
198    // cfft_f32
199    let start = Instant::now();
200    for _ in 0..FFT_ITERATIONS {
201        cfft_f32(&mut fft_data_f32, 256, 0, 1);
202    }
203    let duration_cfft_f32 = start.elapsed();
204
205    // cfft_q31
206    let start = Instant::now();
207    for _ in 0..FFT_ITERATIONS {
208        cfft_q31(&mut fft_data_q31, 256, 0, 1);
209    }
210    let duration_cfft_q31 = start.elapsed();
211
212    // cfft_q15
213    let start = Instant::now();
214    for _ in 0..FFT_ITERATIONS {
215        cfft_q15(&mut fft_data_q15, 256, 0, 1);
216    }
217    let duration_cfft_q15 = start.elapsed();
218
219    println!("  • cfft_f32 (256-pt)  : {:>9.2?}", duration_cfft_f32);
220    println!("  • cfft_q31 (256-pt)  : {:>9.2?}", duration_cfft_q31);
221    println!("  • cfft_q15 (256-pt)  : {:>9.2?}", duration_cfft_q15);
222    println!();
223    println!(
224        "========================================================================================="
225    );
226}