use std::any::type_name; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use p3_baby_bear::BabyBear; use p3_dft::{Radix2Bowers, Radix2Dit, Radix2DitParallel, TwoAdicSubgroupDft}; use p3_field::extension::Complex; use p3_field::TwoAdicField; use p3_goldilocks::Goldilocks; use p3_matrix::dense::RowMajorMatrix; use p3_mersenne_31::{Mersenne31, Mersenne31ComplexRadix2Dit, Mersenne31Dft}; use rand::distributions::{Distribution, Standard}; use rand::thread_rng; fn bench_fft(c: &mut Criterion) { // log_sizes correspond to the sizes of DFT we want to benchmark; // for the DFT over the quadratic extension "Mersenne31Complex" a // fairer comparison is to use half sizes, which is the log minus 1. let log_sizes = &[14, 16, 18]; let log_half_sizes = &[13, 15, 17]; const BATCH_SIZE: usize = 100; fft::, BATCH_SIZE>(c, log_sizes); fft::(c, log_sizes); fft::(c, log_sizes); fft::, BATCH_SIZE>(c, log_sizes); fft::(c, log_sizes); fft::(c, log_sizes); fft::, Radix2Dit<_>, BATCH_SIZE>(c, log_half_sizes); fft::, Radix2Bowers, BATCH_SIZE>(c, log_half_sizes); fft::, Radix2DitParallel, BATCH_SIZE>(c, log_half_sizes); fft::, Mersenne31ComplexRadix2Dit, BATCH_SIZE>(c, log_half_sizes); m31_fft::, BATCH_SIZE>(c, log_sizes); m31_fft::(c, log_sizes); ifft::, BATCH_SIZE>(c); coset_lde::(c); coset_lde::(c); coset_lde::(c); } fn fft(c: &mut Criterion, log_sizes: &[usize]) where F: TwoAdicField, Dft: TwoAdicSubgroupDft, Standard: Distribution, { let mut group = c.benchmark_group(&format!( "fft::<{}, {}, {}>", type_name::(), type_name::(), BATCH_SIZE )); group.sample_size(10); let mut rng = thread_rng(); for n_log in log_sizes { let n = 1 << n_log; let messages = RowMajorMatrix::rand(&mut rng, n, BATCH_SIZE); let dft = Dft::default(); group.bench_with_input(BenchmarkId::from_parameter(n), &dft, |b, dft| { b.iter(|| { dft.dft_batch(messages.clone()); }); }); } } fn m31_fft(c: &mut Criterion, log_sizes: &[usize]) where Dft: TwoAdicSubgroupDft>, Standard: Distribution, { let mut group = c.benchmark_group(&format!( "m31_fft::<{}, {}>", type_name::(), BATCH_SIZE )); group.sample_size(10); let mut rng = thread_rng(); for n_log in log_sizes { let n = 1 << n_log; let messages = RowMajorMatrix::rand(&mut rng, n, BATCH_SIZE); group.bench_function(BenchmarkId::from_parameter(n), |b| { b.iter(|| { Mersenne31Dft::dft_batch::(messages.clone()); }); }); } } fn ifft(c: &mut Criterion) where F: TwoAdicField, Dft: TwoAdicSubgroupDft, Standard: Distribution, { let mut group = c.benchmark_group(&format!( "ifft::<{}, {}, {}>", type_name::(), type_name::(), BATCH_SIZE )); group.sample_size(10); let mut rng = thread_rng(); for n_log in [14, 16, 18] { let n = 1 << n_log; let messages = RowMajorMatrix::rand(&mut rng, n, BATCH_SIZE); let dft = Dft::default(); group.bench_with_input(BenchmarkId::from_parameter(n), &dft, |b, dft| { b.iter(|| { dft.idft_batch(messages.clone()); }); }); } } fn coset_lde(c: &mut Criterion) where F: TwoAdicField, Dft: TwoAdicSubgroupDft, Standard: Distribution, { let mut group = c.benchmark_group(&format!( "coset_lde::<{}, {}, {}>", type_name::(), type_name::(), BATCH_SIZE )); group.sample_size(10); let mut rng = thread_rng(); for n_log in [14, 16, 18] { let n = 1 << n_log; let messages = RowMajorMatrix::rand(&mut rng, n, BATCH_SIZE); let dft = Dft::default(); group.bench_with_input(BenchmarkId::from_parameter(n), &dft, |b, dft| { b.iter(|| { dft.coset_lde_batch(messages.clone(), 1, F::generator()); }); }); } } criterion_group!(benches, bench_fft); criterion_main!(benches);