use std::hint::black_box; use criterion::{BenchmarkId, Criterion}; use crate::{ api::{ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxRotate, VecZnxRotateInplace, VecZnxRotateInplaceTmpBytes}, layouts::{Backend, FillUniform, Module, ScratchOwned, VecZnx, VecZnxToMut, VecZnxToRef, ZnxInfos, ZnxView, ZnxViewMut}, reference::znx::{ZnxCopy, ZnxRotate, ZnxZero}, source::Source, }; pub fn vec_znx_rotate_inplace_tmp_bytes(n: usize) -> usize { n * size_of::() } pub fn vec_znx_rotate(p: i64, res: &mut R, res_col: usize, a: &A, a_col: usize) where R: VecZnxToMut, A: VecZnxToRef, ZNXARI: ZnxRotate + ZnxZero, { let mut res: VecZnx<&mut [u8]> = res.to_mut(); let a: VecZnx<&[u8]> = a.to_ref(); #[cfg(debug_assertions)] { assert_eq!(res.n(), a.n()) } let res_size: usize = res.size(); let a_size: usize = a.size(); let min_size: usize = res_size.min(a_size); for j in 0..min_size { ZNXARI::znx_rotate(p, res.at_mut(res_col, j), a.at(a_col, j)) } for j in min_size..res_size { ZNXARI::znx_zero(res.at_mut(res_col, j)); } } pub fn vec_znx_rotate_inplace(p: i64, res: &mut R, res_col: usize, tmp: &mut [i64]) where R: VecZnxToMut, ZNXARI: ZnxRotate + ZnxCopy, { let mut res: VecZnx<&mut [u8]> = res.to_mut(); #[cfg(debug_assertions)] { assert_eq!(res.n(), tmp.len()); } for j in 0..res.size() { ZNXARI::znx_rotate(p, tmp, res.at(res_col, j)); ZNXARI::znx_copy(res.at_mut(res_col, j), tmp); } } pub fn bench_vec_znx_rotate(c: &mut Criterion, label: &str) where Module: VecZnxRotate + ModuleNew, { let group_name: String = format!("vec_znx_rotate::{label}"); let mut group = c.benchmark_group(group_name); fn runner(params: [usize; 3]) -> impl FnMut() where Module: VecZnxRotate + ModuleNew, { let n: usize = 1 << params[0]; let cols: usize = params[1]; let size: usize = params[2]; let module: Module = Module::::new(n as u64); let mut source: Source = Source::new([0u8; 32]); let mut a: VecZnx> = VecZnx::alloc(n, cols, size); let mut res: VecZnx> = VecZnx::alloc(n, cols, size); // Fill a with random i64 a.fill_uniform(50, &mut source); res.fill_uniform(50, &mut source); move || { for i in 0..cols { module.vec_znx_rotate(-7, &mut res, i, &a, i); } black_box(()); } } for params in [[10, 2, 2], [11, 2, 4], [12, 2, 8], [13, 2, 16], [14, 2, 32]] { let id: BenchmarkId = BenchmarkId::from_parameter(format!("{}x({}x{})", 1 << params[0], params[1], params[2],)); let mut runner = runner::(params); group.bench_with_input(id, &(), |b, _| b.iter(&mut runner)); } group.finish(); } pub fn bench_vec_znx_rotate_inplace(c: &mut Criterion, label: &str) where Module: VecZnxRotateInplace + VecZnxRotateInplaceTmpBytes + ModuleNew, ScratchOwned: ScratchOwnedAlloc + ScratchOwnedBorrow, { let group_name: String = format!("vec_znx_rotate_inplace::{label}"); let mut group = c.benchmark_group(group_name); fn runner(params: [usize; 3]) -> impl FnMut() where Module: VecZnxRotateInplace + ModuleNew + VecZnxRotateInplaceTmpBytes, ScratchOwned: ScratchOwnedAlloc + ScratchOwnedBorrow, { let n: usize = 1 << params[0]; let cols: usize = params[1]; let size: usize = params[2]; let module: Module = Module::::new(n as u64); let mut source: Source = Source::new([0u8; 32]); let mut res: VecZnx> = VecZnx::alloc(n, cols, size); let mut scratch = ScratchOwned::alloc(module.vec_znx_rotate_inplace_tmp_bytes()); // Fill a with random i64 res.fill_uniform(50, &mut source); move || { for i in 0..cols { module.vec_znx_rotate_inplace(-7, &mut res, i, scratch.borrow()); } black_box(()); } } for params in [[10, 2, 2], [11, 2, 4], [12, 2, 8], [13, 2, 16], [14, 2, 32]] { let id: BenchmarkId = BenchmarkId::from_parameter(format!("{}x({}x{})", 1 << params[0], params[1], params[2],)); let mut runner = runner::(params); group.bench_with_input(id, &(), |b, _| b.iter(&mut runner)); } group.finish(); }