diff --git a/Cargo.lock b/Cargo.lock index 7bbc290..631a1f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -637,6 +637,7 @@ name = "rlwe" version = "0.1.0" dependencies = [ "base2k", + "criterion", "rand_distr", "sampling", ] diff --git a/rlwe/Cargo.toml b/rlwe/Cargo.toml index a5d94c8..cf4ae7a 100644 --- a/rlwe/Cargo.toml +++ b/rlwe/Cargo.toml @@ -6,6 +6,11 @@ version = "0.1.0" edition = "2024" [dependencies] +criterion = {workspace = true} base2k = {path="../base2k"} sampling = {path="../sampling"} rand_distr = {workspace = true} + +[[bench]] +name = "gadget_product" +harness = false \ No newline at end of file diff --git a/rlwe/benches/gadget_product.rs b/rlwe/benches/gadget_product.rs new file mode 100644 index 0000000..df62299 --- /dev/null +++ b/rlwe/benches/gadget_product.rs @@ -0,0 +1,133 @@ +use base2k::{ + Encoding, FFT64, Infos, Module, Sampling, Scalar, SvpPPolOps, VecZnx, VecZnxBig, VecZnxDft, + VecZnxOps, +}; +use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main}; +use rlwe::{ + ciphertext::{Ciphertext, GadgetCiphertext}, + decryptor::{Decryptor, decrypt_rlwe_thread_safe, decrypt_rlwe_thread_safe_tmp_byte}, + elem::Elem, + encryptor::{ + EncryptorSk, encrypt_grlwe_sk_thread_safe, encrypt_grlwe_sk_tmp_bytes, + encrypt_rlwe_sk_tmp_bytes, + }, + evaluator::{gadget_product_inplace_thread_safe, gadget_product_tmp_bytes}, + key_generator::{gen_switching_key_thread_safe, gen_switching_key_thread_safe_tmp_bytes}, + keys::{SecretKey, SwitchingKey}, + parameters::{Parameters, ParametersLiteral}, + plaintext::Plaintext, +}; +use sampling::source::{Source, new_seed}; + +fn gadget_product_inplace(c: &mut Criterion) { + fn gadget_product<'a>( + module: &'a Module, + elem: &'a mut Elem, + gadget_ct: &'a GadgetCiphertext, + tmp_bytes: &'a mut [u8], + ) -> Box { + Box::new(move || { + gadget_product_inplace_thread_safe::(module, elem, gadget_ct, tmp_bytes) + }) + } + + let mut b: criterion::BenchmarkGroup<'_, criterion::measurement::WallTime> = + c.benchmark_group("gadget_product_inplace"); + + for log_n in 10..11 { + let params_lit: ParametersLiteral = ParametersLiteral { + log_n: log_n, + log_q: 54, + log_p: 0, + log_base2k: 7, + log_scale: 20, + xe: 3.2, + xs: 128, + }; + + let params: Parameters = Parameters::new::(¶ms_lit); + + let mut tmp_bytes: Vec = vec![ + 0u8; + params.decrypt_rlwe_thread_safe_tmp_byte(params.log_q()) + | params.encrypt_rlwe_sk_tmp_bytes(params.log_q()) + | gen_switching_key_thread_safe_tmp_bytes( + params.module(), + params.log_base2k(), + params.limbs_q(), + params.log_q() + ) + | gadget_product_tmp_bytes( + params.module(), + params.log_base2k(), + params.log_q(), + params.log_q(), + params.limbs_q(), + params.log_qp() + ) + | encrypt_grlwe_sk_tmp_bytes( + params.module(), + params.log_base2k(), + params.limbs_qp(), + params.log_qp() + ) + ]; + + let mut source: Source = Source::new([3; 32]); + + let mut sk0: SecretKey = SecretKey::new(params.module()); + let mut sk1: SecretKey = SecretKey::new(params.module()); + + let mut source_xe: Source = Source::new([4; 32]); + let mut source_xa: Source = Source::new([5; 32]); + + let mut sk0_svp_ppol: base2k::SvpPPol = params.module().new_svp_ppol(); + params.module().svp_prepare(&mut sk0_svp_ppol, &sk0.0); + + let mut sk1_svp_ppol: base2k::SvpPPol = params.module().new_svp_ppol(); + params.module().svp_prepare(&mut sk1_svp_ppol, &sk1.0); + + let mut gadget_ct: GadgetCiphertext = GadgetCiphertext::new( + params.module(), + params.log_base2k(), + params.limbs_q(), + params.log_qp(), + ); + + encrypt_grlwe_sk_thread_safe( + params.module(), + &mut gadget_ct, + &sk0.0, + &sk1_svp_ppol, + &mut source_xa, + &mut source_xe, + params.xe(), + &mut tmp_bytes, + ); + + let mut ct: Ciphertext = params.new_ciphertext(params.log_q()); + + params.encrypt_rlwe_sk_thread_safe( + &mut ct, + None, + &sk0_svp_ppol, + &mut source_xa, + &mut source_xe, + &mut tmp_bytes, + ); + + let runners: [(String, Box); 1] = [(format!("gadget_product"), { + gadget_product(params.module(), &mut ct.0, &gadget_ct, &mut tmp_bytes) + })]; + + for (name, mut runner) in runners { + let id: BenchmarkId = BenchmarkId::new(name, format!("n={}", 1 << log_n)); + b.bench_with_input(id, &(), |b: &mut criterion::Bencher<'_>, _| { + b.iter(&mut runner) + }); + } + } +} + +criterion_group!(benches, gadget_product_inplace); +criterion_main!(benches);