added benchmarks for digit decomp
Jean-Philippe Bossuat jeanphilippe.bossuat@gmail.com
Tue, 21 Jan 2025 11:06:37 +0100
2 files changed,
144 insertions(+),
38 deletions(-)
M
math/benches/operations.rs
→
math/benches/operations.rs
@@ -1,25 +1,24 @@
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use math::modulus::montgomery::Montgomery; -use math::modulus::VectorOperations; -use math::modulus::ONCE; +use math::modulus::{WordOps, ONCE}; +use math::poly::Poly; use math::ring::Ring; -use math::CHUNK; -fn va_add_vb_into_vb(c: &mut Criterion) { - fn runner(r: Ring<u64>) -> Box<dyn FnMut()> { - let mut p0: math::poly::Poly<u64> = r.new_poly(); - let mut p1: math::poly::Poly<u64> = r.new_poly(); - for i in 0..p0.n() { - p0.0[i] = i as u64; - p1.0[i] = i as u64; +fn a_add_b_into_b(c: &mut Criterion) { + fn runner(ring: Ring<u64>) -> Box<dyn FnMut()> { + let mut a: Poly<u64> = ring.new_poly(); + let mut b: Poly<u64> = ring.new_poly(); + for i in 0..ring.n() { + a.0[i] = i as u64; + b.0[i] = i as u64; } Box::new(move || { - r.modulus.va_add_vb_into_vb::<CHUNK, ONCE>(&p0.0, &mut p1.0); + ring.a_add_b_into_b::<ONCE>(&a, &mut b); }) } let mut b: criterion::BenchmarkGroup<'_, criterion::measurement::WallTime> = - c.benchmark_group("va_add_vb_into_vb"); + c.benchmark_group("a_add_b_into_b"); for log_n in 11..17 { let n: usize = 1 << log_n as usize; let q_base: u64 = 0x1fffffffffe00001u64;@@ -33,22 +32,21 @@ }
} } -fn va_mont_mul_vb_into_vb(c: &mut Criterion) { - fn runner(r: Ring<u64>) -> Box<dyn FnMut()> { - let mut p0: math::poly::Poly<Montgomery<u64>> = r.new_poly(); - let mut p1: math::poly::Poly<u64> = r.new_poly(); - for i in 0..p0.n() { - p0.0[i] = r.modulus.montgomery.prepare::<ONCE>(i as u64); - p1.0[i] = i as u64; +fn a_mul_b_montgomery_into_a(c: &mut Criterion) { + fn runner(ring: Ring<u64>) -> Box<dyn FnMut()> { + let mut a: Poly<Montgomery<u64>> = ring.new_poly(); + let mut b: Poly<u64> = ring.new_poly(); + for i in 0..ring.n() { + a.0[i] = ring.modulus.montgomery.prepare::<ONCE>(i as u64); + b.0[i] = i as u64; } Box::new(move || { - r.modulus - .va_mont_mul_vb_into_vb::<CHUNK, ONCE>(&p0.0, &mut p1.0); + ring.a_mul_b_montgomery_into_a::<ONCE>(&a, &mut b); }) } let mut b: criterion::BenchmarkGroup<'_, criterion::measurement::WallTime> = - c.benchmark_group("va_mont_mul_vb_into_vb"); + c.benchmark_group("a_mul_b_montgomery_into_a"); for log_n in 11..17 { let n: usize = 1 << log_n as usize; let q_base: u64 = 0x1fffffffffe00001u64;@@ -62,23 +60,22 @@ }
} } -fn va_mont_mul_vb_into_vc(c: &mut Criterion) { - fn runner(r: Ring<u64>) -> Box<dyn FnMut()> { - let mut p0: math::poly::Poly<Montgomery<u64>> = r.new_poly(); - let mut p1: math::poly::Poly<u64> = r.new_poly(); - let mut p2: math::poly::Poly<u64> = r.new_poly(); - for i in 0..p0.n() { - p0.0[i] = r.modulus.montgomery.prepare::<ONCE>(i as u64); - p1.0[i] = i as u64; +fn a_mul_b_montgomery_into_c(c: &mut Criterion) { + fn runner(ring: Ring<u64>) -> Box<dyn FnMut()> { + let mut a: Poly<Montgomery<u64>> = ring.new_poly(); + let mut b: Poly<u64> = ring.new_poly(); + let mut c: Poly<u64> = ring.new_poly(); + for i in 0..ring.n() { + a.0[i] = ring.modulus.montgomery.prepare::<ONCE>(i as u64); + b.0[i] = i as u64; } Box::new(move || { - r.modulus - .va_mont_mul_vb_into_vc::<CHUNK, ONCE>(&p0.0, &p1.0, &mut p2.0); + ring.a_mul_b_montgomery_into_c::<ONCE>(&a, &b, &mut c); }) } let mut b: criterion::BenchmarkGroup<'_, criterion::measurement::WallTime> = - c.benchmark_group("va_mont_mul_vb_into_vc"); + c.benchmark_group("a_mul_b_montgomery_into_c"); for log_n in 11..17 { let n: usize = 1 << log_n as usize; let q_base: u64 = 0x1fffffffffe00001u64;@@ -92,10 +89,121 @@ }
} } +fn a_ith_digit_unsigned_base_scalar_b_into_c(c: &mut Criterion) { + fn runner(ring: Ring<u64>, base: usize, d: usize) -> Box<dyn FnMut()> { + let mut a: Poly<Montgomery<u64>> = ring.new_poly(); + let mut b: Poly<u64> = ring.new_poly(); + for i in 0..ring.n() { + a.0[i] = i as u64; + } + Box::new(move || { + (0..d).for_each(|i| { + ring.a_ith_digit_unsigned_base_scalar_b_into_c(i, &a, &base, &mut b); + }) + }) + } + + let mut b: criterion::BenchmarkGroup<'_, criterion::measurement::WallTime> = + c.benchmark_group("a_ith_digit_unsigned_base_scalar_b_into_c"); + for log_n in 11..12 { + let n: usize = 1 << log_n as usize; + let q_base: u64 = 0x1fffffffffe00001u64; + let q_power: usize = 1usize; + let ring: Ring<u64> = Ring::<u64>::new(n, q_base, q_power); + let base: usize = 7; + let logq: usize = ring.modulus.q.log2(); + let d: usize = (logq + base - 1) / base; + let runners = [(format!("prime/logq={}/w={}/d={}", logq, base, d), { + runner(ring, base, d) + })]; + for (name, mut runner) in runners { + let id = BenchmarkId::new(name, n); + b.bench_with_input(id, &(), |b, _| b.iter(&mut runner)); + } + } +} + +fn a_ith_digit_signed_base_scalar_b_into_c_balanced_false(c: &mut Criterion) { + fn runner(ring: Ring<u64>, base: usize, d: usize) -> Box<dyn FnMut()> { + let mut a: Poly<Montgomery<u64>> = ring.new_poly(); + let mut carry: Poly<u64> = ring.new_poly(); + let mut b: Poly<u64> = ring.new_poly(); + for i in 0..ring.n() { + a.0[i] = i as u64; + } + Box::new(move || { + (0..d).for_each(|i| { + ring.a_ith_digit_signed_base_scalar_b_into_c::<false>( + i, &a, &base, &mut carry, &mut b, + ); + }) + }) + } + + let mut b: criterion::BenchmarkGroup<'_, criterion::measurement::WallTime> = + c.benchmark_group("a_ith_digit_signed_base_scalar_b_into_c::<BALANCED=false>"); + for log_n in 11..12 { + let n: usize = 1 << log_n as usize; + let q_base: u64 = 0x1fffffffffe00001u64; + let q_power: usize = 1usize; + let ring: Ring<u64> = Ring::<u64>::new(n, q_base, q_power); + let base: usize = 7; + let logq: usize = ring.modulus.q.log2(); + let d: usize = (logq + base - 1) / base; + let runners = [(format!("prime/logq={}/w={}/d={}", logq, base, d), { + runner(ring, base, d) + })]; + for (name, mut runner) in runners { + let id = BenchmarkId::new(name, n); + b.bench_with_input(id, &(), |b, _| b.iter(&mut runner)); + } + } +} + +fn a_ith_digit_signed_base_scalar_b_into_c_balanced_true(c: &mut Criterion) { + fn runner(ring: Ring<u64>, base: usize, d: usize) -> Box<dyn FnMut()> { + let mut a: Poly<Montgomery<u64>> = ring.new_poly(); + let mut carry: Poly<u64> = ring.new_poly(); + let mut b: Poly<u64> = ring.new_poly(); + for i in 0..ring.n() { + a.0[i] = i as u64; + } + Box::new(move || { + (0..d).for_each(|i| { + ring.a_ith_digit_signed_base_scalar_b_into_c::<true>( + i, &a, &base, &mut carry, &mut b, + ); + }) + }) + } + + let mut b: criterion::BenchmarkGroup<'_, criterion::measurement::WallTime> = + c.benchmark_group("a_ith_digit_signed_base_scalar_b_into_c::<BALANCED=true>"); + for log_n in 11..12 { + let n: usize = 1 << log_n as usize; + let q_base: u64 = 0x1fffffffffe00001u64; + let q_power: usize = 1usize; + let ring: Ring<u64> = Ring::<u64>::new(n, q_base, q_power); + let base: usize = 7; + let logq: usize = ring.modulus.q.log2(); + let d: usize = (logq + base - 1) / base; + let runners = [(format!("prime/logq={}/w={}/d={}", logq, base, d), { + runner(ring, base, d) + })]; + for (name, mut runner) in runners { + let id = BenchmarkId::new(name, n); + b.bench_with_input(id, &(), |b, _| b.iter(&mut runner)); + } + } +} + criterion_group!( benches, - va_add_vb_into_vb, - va_mont_mul_vb_into_vb, - va_mont_mul_vb_into_vc + a_add_b_into_b, + a_mul_b_montgomery_into_a, + a_mul_b_montgomery_into_c, + a_ith_digit_unsigned_base_scalar_b_into_c, + a_ith_digit_signed_base_scalar_b_into_c_balanced_false, + a_ith_digit_signed_base_scalar_b_into_c_balanced_true, ); criterion_main!(benches);
M
math/tests/ring_switch.rs
→
math/tests/ring_switch.rs
@@ -1,5 +1,3 @@
-use itertools::izip; -use math::automorphism::AutoPerm; use math::poly::Poly; use math::ring::Ring;