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