poulpy/poulpy-backend/benches/fft.rs
poulpy-backend/benches/fft.rsRaw
1use std::{ffi::c_void, hint::black_box};
2
3use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
4use poulpy_backend::cpu_spqlios::reim;
5use poulpy_hal::reference::fft64::reim::{ReimDFTExecute, ReimFFTRef, ReimFFTTable, ReimIFFTRef, ReimIFFTTable};
6
7pub fn bench_fft_ref(c: &mut Criterion) {
8 let group_name: String = "fft_ref".to_string();
9
10 let mut group = c.benchmark_group(group_name);
11
12 fn runner(m: usize) -> impl FnMut() {
13 let mut values: Vec<f64> = vec![0f64; m << 1];
14 let scale: f64 = 1.0f64 / (2 * m) as f64;
15 values
16 .iter_mut()
17 .enumerate()
18 .for_each(|(i, x)| *x = (i + 1) as f64 * scale);
19 let table: ReimFFTTable<f64> = ReimFFTTable::<f64>::new(m);
20 move || {
21 ReimFFTRef::reim_dft_execute(&table, &mut values);
22 black_box(());
23 }
24 }
25
26 for log_m in [9, 10, 11, 12, 13, 14, 15] {
27 let id: BenchmarkId = BenchmarkId::from_parameter(format!("n: {}", 2 << log_m));
28 let mut runner = runner(1 << log_m);
29 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
30 }
31
32 group.finish();
33}
34
35pub fn bench_fft_spqlios(c: &mut Criterion) {
36 let group_name: String = "fft_spqlios".to_string();
37
38 let mut group = c.benchmark_group(group_name);
39
40 fn runner(m: usize) -> impl FnMut() {
41 let mut values: Vec<f64> = vec![0f64; m << 1];
42
43 let scale = 1.0f64 / (2 * m) as f64;
44 values
45 .iter_mut()
46 .enumerate()
47 .for_each(|(i, x)| *x = (i + 1) as f64 * scale);
48
49 unsafe {
50 reim::reim_fft_simple(m as u32, values.as_mut_ptr() as *mut c_void);
51 }
52
53 move || {
54 unsafe {
55 reim::reim_fft_simple(m as u32, values.as_mut_ptr() as *mut c_void);
56 }
57 black_box(());
58 }
59 }
60
61 for log_m in [9, 10, 11, 12, 13, 14, 15] {
62 let id: BenchmarkId = BenchmarkId::from_parameter(format!("n: {}", 2 << log_m));
63 let mut runner = runner(1 << log_m);
64 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
65 }
66
67 group.finish();
68}
69
70pub fn bench_ifft_ref(c: &mut Criterion) {
71 let group_name: String = "ifft_ref".to_string();
72
73 let mut group = c.benchmark_group(group_name);
74
75 fn runner(m: usize) -> impl FnMut() {
76 let mut values: Vec<f64> = vec![0f64; m << 1];
77 let scale: f64 = 1.0f64 / (2 * m) as f64;
78 values
79 .iter_mut()
80 .enumerate()
81 .for_each(|(i, x)| *x = (i + 1) as f64 * scale);
82 let table: ReimIFFTTable<f64> = ReimIFFTTable::<f64>::new(m);
83 move || {
84 ReimIFFTRef::reim_dft_execute(&table, &mut values);
85 black_box(());
86 }
87 }
88
89 for log_m in [9, 10, 11, 12, 13, 14, 15] {
90 let id: BenchmarkId = BenchmarkId::from_parameter(format!("n: {}", 2 << log_m));
91 let mut runner = runner(1 << log_m);
92 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
93 }
94
95 group.finish();
96}
97
98pub fn bench_ifft_spqlios(c: &mut Criterion) {
99 let group_name: String = "ifft_spqlios".to_string();
100
101 let mut group = c.benchmark_group(group_name);
102
103 fn runner(m: usize) -> impl FnMut() {
104 let mut values: Vec<f64> = vec![0f64; m << 1];
105
106 let scale = 1.0f64 / (2 * m) as f64;
107 values
108 .iter_mut()
109 .enumerate()
110 .for_each(|(i, x)| *x = (i + 1) as f64 * scale);
111
112 unsafe {
113 reim::reim_ifft_simple(m as u32, values.as_mut_ptr() as *mut c_void);
114 }
115
116 move || {
117 unsafe {
118 reim::reim_ifft_simple(m as u32, values.as_mut_ptr() as *mut c_void);
119 }
120 black_box(());
121 }
122 }
123
124 for log_m in [9, 10, 11, 12, 13, 14, 15] {
125 let id: BenchmarkId = BenchmarkId::from_parameter(format!("n: {}", 2 << log_m));
126 let mut runner = runner(1 << log_m);
127 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
128 }
129
130 group.finish();
131}
132
133#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
134mod x86 {
135 use super::*;
136
137 #[allow(dead_code)]
138 pub fn bench_ifft_avx2_fma(c: &mut Criterion) {
139 let group_name: String = "ifft_avx2_fma".to_string();
140
141 let mut group = c.benchmark_group(group_name);
142
143 if std::is_x86_feature_detected!("avx2") {
144 fn runner(m: usize) -> impl FnMut() {
145 let mut values: Vec<f64> = vec![0f64; m << 1];
146
147 let scale = 1.0f64 / (2 * m) as f64;
148 values
149 .iter_mut()
150 .enumerate()
151 .for_each(|(i, x)| *x = (i + 1) as f64 * scale);
152
153 let table: ReimIFFTTable<f64> = ReimIFFTTable::<f64>::new(m);
154 move || {
155 use poulpy_backend::cpu_fft64_avx::ReimIFFTAvx;
156
157 ReimIFFTAvx::reim_dft_execute(&table, &mut values);
158 black_box(());
159 }
160 }
161
162 for log_m in [9, 10, 11, 12, 13, 14, 15] {
163 let id: BenchmarkId = BenchmarkId::from_parameter(format!("n: {}", 2 << log_m));
164
165 let mut runner = runner(1 << log_m);
166 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
167 }
168 } else {
169 eprintln!("skipping: CPU lacks avx2");
170 return;
171 }
172
173 group.finish();
174 }
175
176 #[allow(dead_code)]
177 pub fn bench_fft_avx2_fma(c: &mut Criterion) {
178 let group_name: String = "fft_avx2_fma".to_string();
179
180 let mut group = c.benchmark_group(group_name);
181
182 if std::is_x86_feature_detected!("avx2") {
183 fn runner(m: usize) -> impl FnMut() {
184 let mut values: Vec<f64> = vec![0f64; m << 1];
185
186 let scale = 1.0f64 / (2 * m) as f64;
187 values
188 .iter_mut()
189 .enumerate()
190 .for_each(|(i, x)| *x = (i + 1) as f64 * scale);
191
192 let table: ReimFFTTable<f64> = ReimFFTTable::<f64>::new(m);
193 move || {
194 use poulpy_backend::cpu_fft64_avx::ReimFFTAvx;
195
196 ReimFFTAvx::reim_dft_execute(&table, &mut values);
197 black_box(());
198 }
199 }
200
201 for log_m in [9, 10, 11, 12, 13, 14, 15] {
202 let id: BenchmarkId = BenchmarkId::from_parameter(format!("n: {}", 2 << log_m));
203
204 let mut runner = runner(1 << log_m);
205 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
206 }
207 } else {
208 eprintln!("skipping: CPU lacks avx2");
209 return;
210 }
211
212 group.finish();
213 }
214
215 criterion_group!(benches_x86, bench_fft_avx2_fma, bench_ifft_avx2_fma,);
216 criterion_main!(benches_x86);
217}
218
219criterion_group!(
220 benches,
221 bench_fft_ref,
222 bench_fft_spqlios,
223 bench_ifft_ref,
224 bench_ifft_spqlios
225);
226
227criterion_main!(benches);