math/benches/fft.rs (98 lines of code) (raw):

// Copyright (c) Facebook, Inc. and its affiliates. // // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; use rand_utils::rand_vector; use std::time::Duration; use winter_math::{ fft, fields::{f128, f62, f64, QuadExtension}, FieldElement, StarkField, }; const SIZES: [usize; 3] = [262_144, 524_288, 1_048_576]; fn fft_evaluate_poly<B, E>(c: &mut Criterion, field_name: &str) where B: StarkField, E: FieldElement<BaseField = B>, { let mut group = c.benchmark_group(format!("{}/fft_evaluate_poly", field_name)); group.sample_size(10); group.measurement_time(Duration::from_secs(10)); let blowup_factor = 8; for &size in SIZES.iter() { let p: Vec<E> = rand_vector(size / blowup_factor); let twiddles: Vec<B> = fft::get_twiddles(size); group.bench_function(BenchmarkId::new("simple", size), |bench| { bench.iter_with_large_drop(|| { let mut result = vec![E::ZERO; size]; result[..p.len()].copy_from_slice(&p); fft::evaluate_poly(&mut result, &twiddles); result }); }); } for &size in SIZES.iter() { let p: Vec<E> = rand_vector(size / blowup_factor); let twiddles: Vec<B> = fft::get_twiddles(size / blowup_factor); group.bench_function(BenchmarkId::new("with_offset", size), |bench| { bench.iter_with_large_drop(|| { let result = fft::evaluate_poly_with_offset(&p, &twiddles, B::GENERATOR, blowup_factor); result }); }); } group.finish(); } fn fft_interpolate_poly<B, E>(c: &mut Criterion, field_name: &str) where B: StarkField, E: FieldElement<BaseField = B>, { let mut group = c.benchmark_group(format!("{}/fft_interpolate_poly", field_name)); group.sample_size(10); group.measurement_time(Duration::from_secs(10)); for &size in SIZES.iter() { let p: Vec<E> = rand_vector(size); let inv_twiddles: Vec<B> = fft::get_inv_twiddles(size); group.bench_function(BenchmarkId::new("simple", size), |bench| { bench.iter_batched_ref( || p.clone(), |mut p| fft::interpolate_poly(&mut p, &inv_twiddles), BatchSize::LargeInput, ); }); } for &size in SIZES.iter() { let p: Vec<E> = rand_vector(size); let inv_twiddles: Vec<B> = fft::get_inv_twiddles(size); group.bench_function(BenchmarkId::new("with_offset", size), |bench| { bench.iter_batched_ref( || p.clone(), |mut p| fft::interpolate_poly_with_offset(&mut p, &inv_twiddles, B::GENERATOR), BatchSize::LargeInput, ); }); } group.finish(); } fn get_twiddles(c: &mut Criterion) { let mut group = c.benchmark_group("fft_get_twiddles"); group.sample_size(10); for &size in SIZES.iter() { group.bench_with_input(BenchmarkId::from_parameter(size), &size, |bench, &size| { bench.iter(|| fft::get_twiddles::<f128::BaseElement>(size)); }); } group.finish(); } fn bench_fft(c: &mut Criterion) { fft_evaluate_poly::<f62::BaseElement, f62::BaseElement>(c, "f62"); fft_evaluate_poly::<f64::BaseElement, f64::BaseElement>(c, "f64"); fft_evaluate_poly::<f128::BaseElement, f128::BaseElement>(c, "f128"); fft_evaluate_poly::<f62::BaseElement, QuadExtension<f62::BaseElement>>(c, "f62_quad"); fft_evaluate_poly::<f64::BaseElement, QuadExtension<f64::BaseElement>>(c, "f64_quad"); fft_evaluate_poly::<f128::BaseElement, QuadExtension<f128::BaseElement>>(c, "f128_quad"); fft_interpolate_poly::<f62::BaseElement, f62::BaseElement>(c, "f62"); fft_interpolate_poly::<f64::BaseElement, f64::BaseElement>(c, "f64"); fft_interpolate_poly::<f128::BaseElement, f128::BaseElement>(c, "f128"); } criterion_group!(fft_group, bench_fft, get_twiddles); criterion_main!(fft_group);