arnaucube
arnaucube/poulpyPublic Self-hosted repository
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);