From 5659195dbcf5699d0789a1375f54de950191345d Mon Sep 17 00:00:00 2001 From: "Mayeul@Zama" Date: Mon, 17 Apr 2023 17:20:38 +0200 Subject: [PATCH] feat(optimizer): accept any ciphertext_modulus_log --- .../concretelang-c/Support/CompilerEngine.h | 8 ++--- .../concretelang/Support/V0Parameters.h | 3 ++ .../lib/Bindings/Rust/src/compiler.rs | 1 + .../lib/CAPI/Support/CompilerEngine.cpp | 4 ++- .../compiler/lib/Support/V0Parameters.cpp | 1 + .../charts/src/bin/norm2_complexity.rs | 12 +++++-- .../charts/src/bin/precision_complexity.rs | 12 +++++-- .../src/concrete-optimizer.rs | 10 +++--- .../src/cpp/concrete-optimizer.cpp | 1 + .../src/cpp/concrete-optimizer.hpp | 1 + .../concrete-optimizer-cpp/tests/src/main.cpp | 25 ++++++++------- .../dag/multi_parameters/fast_keyswitch.rs | 10 ++++-- .../dag/multi_parameters/optimize.rs | 18 +++++++++-- .../multi_parameters/tests/test_optimize.rs | 4 ++- .../src/optimization/dag/solo_key/optimize.rs | 4 ++- .../decomposition/circuit_bootstrap.rs | 5 ++- .../src/optimization/decomposition/cmux.rs | 7 ++--- .../optimization/decomposition/keyswitch.rs | 8 ++--- .../src/optimization/decomposition/mod.rs | 31 ++++++++++++++++--- .../optimization/decomposition/pp_switch.rs | 7 +++-- .../v0-parameters/benches/benchmark.rs | 3 ++ .../v0-parameters/src/lib.rs | 15 +++++++-- 22 files changed, 139 insertions(+), 51 deletions(-) diff --git a/compilers/concrete-compiler/compiler/include/concretelang-c/Support/CompilerEngine.h b/compilers/concrete-compiler/compiler/include/concretelang-c/Support/CompilerEngine.h index 4ec644a49..8aa2a33bf 100644 --- a/compilers/concrete-compiler/compiler/include/concretelang-c/Support/CompilerEngine.h +++ b/compilers/concrete-compiler/compiler/include/concretelang-c/Support/CompilerEngine.h @@ -148,10 +148,10 @@ MLIR_CAPI_EXPORTED void compilationOptionsDestroy(CompilationOptions options); /// ********** OptimizerConfig CAPI ******************************************** -MLIR_CAPI_EXPORTED OptimizerConfig -optimizerConfigCreate(bool display, double fallback_log_norm_woppbs, - double global_p_error, double p_error, uint64_t security, - bool strategy_v0, bool use_gpu_constraints); +MLIR_CAPI_EXPORTED OptimizerConfig optimizerConfigCreate( + bool display, double fallback_log_norm_woppbs, double global_p_error, + double p_error, uint64_t security, bool strategy_v0, + bool use_gpu_constraints, uint32_t ciphertext_modulus_log); MLIR_CAPI_EXPORTED OptimizerConfig optimizerConfigCreateDefault(); diff --git a/compilers/concrete-compiler/compiler/include/concretelang/Support/V0Parameters.h b/compilers/concrete-compiler/compiler/include/concretelang/Support/V0Parameters.h index 377759877..8556b8a5f 100644 --- a/compilers/concrete-compiler/compiler/include/concretelang/Support/V0Parameters.h +++ b/compilers/concrete-compiler/compiler/include/concretelang/Support/V0Parameters.h @@ -78,6 +78,7 @@ constexpr bool DEFAULT_USE_GPU_CONSTRAINTS = false; constexpr concrete_optimizer::Encoding DEFAULT_ENCODING = concrete_optimizer::Encoding::Auto; constexpr bool DEFAULT_CACHE_ON_DISK = true; +constexpr uint32_t DEFAULT_CIPHERTEXT_MODULUS_LOG = 64; /// The strategy of the crypto optimization enum Strategy { @@ -105,6 +106,7 @@ struct Config { bool use_gpu_constraints; concrete_optimizer::Encoding encoding; bool cache_on_disk; + uint32_t ciphertext_modulus_log; }; constexpr Config DEFAULT_CONFIG = { @@ -117,6 +119,7 @@ constexpr Config DEFAULT_CONFIG = { DEFAULT_USE_GPU_CONSTRAINTS, DEFAULT_ENCODING, DEFAULT_CACHE_ON_DISK, + DEFAULT_CIPHERTEXT_MODULUS_LOG, }; using Dag = rust::Box; diff --git a/compilers/concrete-compiler/compiler/lib/Bindings/Rust/src/compiler.rs b/compilers/concrete-compiler/compiler/lib/Bindings/Rust/src/compiler.rs index ccf7001ce..543339dd8 100644 --- a/compilers/concrete-compiler/compiler/lib/Bindings/Rust/src/compiler.rs +++ b/compilers/concrete-compiler/compiler/lib/Bindings/Rust/src/compiler.rs @@ -369,6 +369,7 @@ impl OptimizerConfig { security, strategy_v0, use_gpu_constraints, + 64, )); if config.is_null() { return Err(CompilerError(config.error_msg())); diff --git a/compilers/concrete-compiler/compiler/lib/CAPI/Support/CompilerEngine.cpp b/compilers/concrete-compiler/compiler/lib/CAPI/Support/CompilerEngine.cpp index 739022954..c51d51982 100644 --- a/compilers/concrete-compiler/compiler/lib/CAPI/Support/CompilerEngine.cpp +++ b/compilers/concrete-compiler/compiler/lib/CAPI/Support/CompilerEngine.cpp @@ -94,7 +94,8 @@ OptimizerConfig double global_p_error, double p_error, uint64_t security, mlir::concretelang::optimizer::Strategy strategy, - bool use_gpu_constraints) { + bool use_gpu_constraints, + uint32_t ciphertext_modulus_log) { auto config = new mlir::concretelang::optimizer::Config(); config->display = display; config->fallback_log_norm_woppbs = fallback_log_norm_woppbs; @@ -103,6 +104,7 @@ OptimizerConfig config->security = security; config->strategy = strategy; config->use_gpu_constraints = use_gpu_constraints; + config->ciphertext_modulus_log = ciphertext_modulus_log; return wrap(config); } diff --git a/compilers/concrete-compiler/compiler/lib/Support/V0Parameters.cpp b/compilers/concrete-compiler/compiler/lib/Support/V0Parameters.cpp index 791c06759..e5c77bc85 100644 --- a/compilers/concrete-compiler/compiler/lib/Support/V0Parameters.cpp +++ b/compilers/concrete-compiler/compiler/lib/Support/V0Parameters.cpp @@ -32,6 +32,7 @@ concrete_optimizer::Options options_from_config(optimizer::Config config) { /* .use_gpu_constraints = */ config.use_gpu_constraints, /* .encoding = */ config.encoding, /* .cache_on_disk = */ config.cache_on_disk, + /* .ciphertext_modulus_log = */ config.ciphertext_modulus_log, }; return options; } diff --git a/compilers/concrete-optimizer/charts/src/bin/norm2_complexity.rs b/compilers/concrete-optimizer/charts/src/bin/norm2_complexity.rs index 123bf5b79..18d1ffdd6 100644 --- a/compilers/concrete-optimizer/charts/src/bin/norm2_complexity.rs +++ b/compilers/concrete-optimizer/charts/src/bin/norm2_complexity.rs @@ -36,14 +36,22 @@ fn main() -> Result<(), Box> { let precision = 8; let log_norm2s = 1_u64..=31; + let ciphertext_modulus_log = 64; + let config = Config { security_level, maximum_acceptable_error_probability: p_error, - ciphertext_modulus_log: 64, + ciphertext_modulus_log, complexity_model: &CpuComplexity::default(), }; - let cache = decomposition::cache(security_level, processing_unit, None, true); + let cache = decomposition::cache( + security_level, + processing_unit, + None, + true, + ciphertext_modulus_log, + ); let solutions: Vec<_> = log_norm2s .clone() diff --git a/compilers/concrete-optimizer/charts/src/bin/precision_complexity.rs b/compilers/concrete-optimizer/charts/src/bin/precision_complexity.rs index cd0d5210f..dd006e90c 100644 --- a/compilers/concrete-optimizer/charts/src/bin/precision_complexity.rs +++ b/compilers/concrete-optimizer/charts/src/bin/precision_complexity.rs @@ -30,6 +30,8 @@ fn main() -> Result<(), Box> { let precisions = 1..=16; let log_norm2 = 10; + let ciphertext_modulus_log = 64; + let search_space = SearchSpace { glwe_log_polynomial_sizes, glwe_dimensions, @@ -39,11 +41,17 @@ fn main() -> Result<(), Box> { let config = Config { security_level, maximum_acceptable_error_probability: p_error, - ciphertext_modulus_log: 64, + ciphertext_modulus_log, complexity_model: &CpuComplexity::default(), }; - let cache = decomposition::cache(security_level, processing_unit, None, true); + let cache = decomposition::cache( + security_level, + processing_unit, + None, + true, + ciphertext_modulus_log, + ); let solutions: Vec<_> = precisions .clone() diff --git a/compilers/concrete-optimizer/concrete-optimizer-cpp/src/concrete-optimizer.rs b/compilers/concrete-optimizer/concrete-optimizer-cpp/src/concrete-optimizer.rs index 84293c98a..eb3db501d 100644 --- a/compilers/concrete-optimizer/concrete-optimizer-cpp/src/concrete-optimizer.rs +++ b/compilers/concrete-optimizer/concrete-optimizer-cpp/src/concrete-optimizer.rs @@ -40,6 +40,7 @@ fn caches_from(options: ffi::Options) -> decomposition::PersistDecompCaches { processing_unit, Some(ProcessingUnit::Cpu.complexity_model()), options.cache_on_disk, + options.ciphertext_modulus_log, ) } @@ -49,7 +50,7 @@ fn optimize_bootstrap(precision: u64, noise_factor: f64, options: ffi::Options) let config = Config { security_level: options.security_level, maximum_acceptable_error_probability: options.maximum_acceptable_error_probability, - ciphertext_modulus_log: 64, + ciphertext_modulus_log: options.ciphertext_modulus_log, complexity_model: &CpuComplexity::default(), }; @@ -489,7 +490,7 @@ impl OperationDag { let config = Config { security_level: options.security_level, maximum_acceptable_error_probability: options.maximum_acceptable_error_probability, - ciphertext_modulus_log: 64, + ciphertext_modulus_log: options.ciphertext_modulus_log, complexity_model: &CpuComplexity::default(), }; @@ -511,7 +512,7 @@ impl OperationDag { let config = Config { security_level: options.security_level, maximum_acceptable_error_probability: options.maximum_acceptable_error_probability, - ciphertext_modulus_log: 64, + ciphertext_modulus_log: options.ciphertext_modulus_log, complexity_model: &CpuComplexity::default(), }; @@ -538,7 +539,7 @@ impl OperationDag { let config = Config { security_level: options.security_level, maximum_acceptable_error_probability: options.maximum_acceptable_error_probability, - ciphertext_modulus_log: 64, + ciphertext_modulus_log: options.ciphertext_modulus_log, complexity_model: &CpuComplexity::default(), }; let search_space = SearchSpace::default(processing_unit); @@ -728,6 +729,7 @@ mod ffi { pub use_gpu_constraints: bool, pub encoding: Encoding, pub cache_on_disk: bool, + pub ciphertext_modulus_log: u32, } #[namespace = "concrete_optimizer::dag"] diff --git a/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.cpp b/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.cpp index 68d54595f..0d13cc9f5 100644 --- a/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.cpp +++ b/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.cpp @@ -1079,6 +1079,7 @@ struct Options final { bool use_gpu_constraints; ::concrete_optimizer::Encoding encoding; bool cache_on_disk; + ::std::uint32_t ciphertext_modulus_log; using IsRelocatable = ::std::true_type; }; diff --git a/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.hpp b/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.hpp index a54a4e5a5..496dc8c2c 100644 --- a/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.hpp +++ b/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.hpp @@ -1060,6 +1060,7 @@ struct Options final { bool use_gpu_constraints; ::concrete_optimizer::Encoding encoding; bool cache_on_disk; + ::std::uint32_t ciphertext_modulus_log; using IsRelocatable = ::std::true_type; }; diff --git a/compilers/concrete-optimizer/concrete-optimizer-cpp/tests/src/main.cpp b/compilers/concrete-optimizer/concrete-optimizer-cpp/tests/src/main.cpp index 3483d8e06..b80f330b3 100644 --- a/compilers/concrete-optimizer/concrete-optimizer-cpp/tests/src/main.cpp +++ b/compilers/concrete-optimizer/concrete-optimizer-cpp/tests/src/main.cpp @@ -16,15 +16,17 @@ const double PRECISION_8B = 8; const double PRECISION_16B = 16; const double WOP_FALLBACK_LOG_NORM = 8; const double NOISE_DEVIATION_COEFF = 1.0; +const uint32_t CIPHERTEXT_MODULUS_LOG = 64; concrete_optimizer::Options default_options() { - return concrete_optimizer::Options { - .security_level = SECURITY_128B, - .maximum_acceptable_error_probability = P_ERROR, - .default_log_norm2_woppbs = WOP_FALLBACK_LOG_NORM, - .use_gpu_constraints = false, - .encoding = concrete_optimizer::Encoding::Auto, - .cache_on_disk = true, + return concrete_optimizer::Options{ + .security_level = SECURITY_128B, + .maximum_acceptable_error_probability = P_ERROR, + .default_log_norm2_woppbs = WOP_FALLBACK_LOG_NORM, + .use_gpu_constraints = false, + .encoding = concrete_optimizer::Encoding::Auto, + .cache_on_disk = true, + .ciphertext_modulus_log = CIPHERTEXT_MODULUS_LOG, }; } @@ -145,7 +147,6 @@ void test_multi_parameters_2_precision() { concrete_optimizer::dag::OperatorIndex input2 = dag->add_input(PRECISION_1B, slice(shape)); - std::vector table = {}; auto lut1 = dag->add_lut(input1, slice(table), PRECISION_8B); auto lut2 = dag->add_lut(input2, slice(table), PRECISION_8B); @@ -165,8 +166,11 @@ void test_multi_parameters_2_precision() { auto secret_keys = circuit_solution.circuit_keys.secret_keys; assert(circuit_solution.circuit_keys.secret_keys.size() == 4); assert(circuit_solution.circuit_keys.bootstrap_keys.size() == 2); - assert(circuit_solution.circuit_keys.keyswitch_keys.size() == 2); // 1 layer so less ks - std::string actual = circuit_solution.circuit_keys.conversion_keyswitch_keys[0].description.c_str(); + assert(circuit_solution.circuit_keys.keyswitch_keys.size() == + 2); // 1 layer so less ks + std::string actual = + circuit_solution.circuit_keys.conversion_keyswitch_keys[0] + .description.c_str(); std::string expected = "fks[1->0]"; assert(actual == expected); } @@ -182,7 +186,6 @@ void test_multi_parameters_2_precision_crt() { concrete_optimizer::dag::OperatorIndex input2 = dag->add_input(PRECISION_1B, slice(shape)); - std::vector table = {}; auto lut1 = dag->add_lut(input1, slice(table), PRECISION_8B); auto lut2 = dag->add_lut(input2, slice(table), PRECISION_8B); diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/fast_keyswitch.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/fast_keyswitch.rs index 9860414cf..75e38ae0c 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/fast_keyswitch.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/fast_keyswitch.rs @@ -36,8 +36,11 @@ fn fft_noise_variance_external_product_glwe( let k = glwe_dimension; assert!(k > 0, "k = {k}"); - // 22 = 2 x 11, 11 = 64 -53 - let scale_margin = (1_u64 << 22) as f64; + assert!(ciphertext_modulus_log > 53); + + let lost_bits = ciphertext_modulus_log - 53; + + let scale_margin = (1_u64 << (2 * lost_bits)) as f64; let res = f64::exp2(FFT_SCALING_WEIGHT) * scale_margin * l * b * b * big_n.powi(2) * (k as f64 + 1.); modular_variance_to_variance(res, ciphertext_modulus_log) @@ -75,6 +78,7 @@ pub fn noise( ks: &KsComplexityNoise, input_glwe: &GlweParameters, output_glwe: &GlweParameters, + ciphertext_modulus_log: u32, ) -> f64 { let N0 = output_glwe.polynomial_size(); let upper_k0 = upper_k0(input_glwe, output_glwe); @@ -84,6 +88,6 @@ pub fn noise( N0, ks.decomp.log2_base, ks.decomp.level, - 64, + ciphertext_modulus_log, ) } diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/optimize.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/optimize.rs index 3cb4bff34..0a6e35364 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/optimize.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/optimize.rs @@ -151,6 +151,7 @@ fn optimize_1_fks_and_all_compatible_ks( complexity: &Complexity, caches: &mut keyswitch::Cache, cut_complexity: f64, + ciphertext_modulus_log: u32, ) -> Option<(Best1FksAndManyKs, OperationsCV)> { // At this point every thing else is known apart fks and ks let input_glwe = macro_parameters[fks_src].glwe_params; @@ -179,7 +180,12 @@ fn optimize_1_fks_and_all_compatible_ks( dst_glwe_param: output_glwe, } } else if use_fast_ks { - let noise = fast_keyswitch::noise(&ks_quantity, &input_glwe, &output_glwe); + let noise = fast_keyswitch::noise( + &ks_quantity, + &input_glwe, + &output_glwe, + ciphertext_modulus_log, + ); let complexity = fast_keyswitch::complexity(&input_glwe, &output_glwe, ks_quantity.decomp.level); FksComplexityNoise { @@ -252,6 +258,7 @@ fn optimize_dst_exclusive_fks_subset_and_all_ks( complexity: &Complexity, caches: &mut keyswitch::Cache, cut_complexity: f64, + ciphertext_modulus_log: u32, ) -> Option<(Vec, OperationsCV)> { // All fks subgroup can be optimized independently let mut acc_operations = operations.clone(); @@ -273,6 +280,7 @@ fn optimize_dst_exclusive_fks_subset_and_all_ks( complexity, caches, cut_complexity, + ciphertext_modulus_log, )?; result.push(bests); _ = std::mem::replace(&mut acc_operations, operations); @@ -309,6 +317,7 @@ fn optimize_1_cmux_and_dst_exclusive_fks_subset_and_all_ks( caches: &mut keyswitch::Cache, cut_complexity: f64, best_p_error: f64, + ciphertext_modulus_log: u32, ) -> Option { let mut operations = operations.clone(); let mut best_sol = None; @@ -338,6 +347,7 @@ fn optimize_1_cmux_and_dst_exclusive_fks_subset_and_all_ks( complexity, caches, best_sol_complexity, + ciphertext_modulus_log, ); if sol.is_none() { continue; @@ -411,6 +421,7 @@ fn apply_fks_variance_and_cost_or_lower_bound( fks_to_optimize: &[Option], used_conversion_keyswitch: &[Vec], operations: &mut OperationsCV, + ciphertext_modulus_log: u32, ) { for (src, dst) in cross_partition(nb_partitions) { if !used_conversion_keyswitch[src][dst] { @@ -449,7 +460,8 @@ fn apply_fks_variance_and_cost_or_lower_bound( // TODO: use a pareto front to avoid that loop if use_fast_ks { for ks_q in ks_pareto { - let variance = fast_keyswitch::noise(ks_q, input_glwe, output_glwe); + let variance = + fast_keyswitch::noise(ks_q, input_glwe, output_glwe, ciphertext_modulus_log); variance_min = variance_min.min(variance); } } else { @@ -693,6 +705,7 @@ fn optimize_macro( &fks_to_optimize, used_conversion_keyswitch, &mut operations, + ciphertext_modulus_log, ); let non_feasible = !feasible.feasible(&operations.variance); @@ -761,6 +774,7 @@ fn optimize_macro( &mut caches.keyswitch, best_complexity, best_p_error, + ciphertext_modulus_log, ); if let Some(some_micro_params) = micro_opt { // erase macros and all fks and ks that can't be real diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/tests/test_optimize.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/tests/test_optimize.rs index 68ed6eb07..157831e46 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/tests/test_optimize.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/tests/test_optimize.rs @@ -14,9 +14,11 @@ mod tests { use crate::optimization::dag::solo_key::optimize::{add_v0_dag, v0_dag}; use crate::optimization::decomposition; + const CIPHERTEXT_MODULUS_LOG: u32 = 64; + static SHARED_CACHES: Lazy = Lazy::new(|| { let processing_unit = config::ProcessingUnit::Cpu; - decomposition::cache(128, processing_unit, None, true) + decomposition::cache(128, processing_unit, None, true, CIPHERTEXT_MODULUS_LOG) }); const _4_SIGMA: f64 = 0.000_063_342_483_999_973; diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/solo_key/optimize.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/solo_key/optimize.rs index f2716e43a..9bb742cef 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/solo_key/optimize.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/solo_key/optimize.rs @@ -461,9 +461,11 @@ pub(crate) mod tests { const _4_SIGMA: f64 = 1.0 - 0.999_936_657_516; + const CIPHERTEXT_MODULUS_LOG: u32 = 64; + static SHARED_CACHES: Lazy = Lazy::new(|| { let processing_unit = config::ProcessingUnit::Cpu; - decomposition::cache(128, processing_unit, None, true) + decomposition::cache(128, processing_unit, None, true, CIPHERTEXT_MODULUS_LOG) }); pub fn optimize(dag: &unparametrized::OperationDag) -> OptimizationState { diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/circuit_bootstrap.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/circuit_bootstrap.rs index ada52f3c0..2a8a9cee2 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/circuit_bootstrap.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/circuit_bootstrap.rs @@ -33,7 +33,6 @@ pub fn pareto_quantities( ciphertext_modulus_log: u32, glwe_params: GlweParameters, ) -> Vec { - assert!(ciphertext_modulus_log == 64); let cmux_param = |level, log2_base| { let br_decomposition_parameter = BrDecompositionParameters { level, log2_base }; CmuxParameters { @@ -41,7 +40,7 @@ pub fn pareto_quantities( output_glwe_params: glwe_params, } }; - let mut quantities = Vec::with_capacity(64); + let mut quantities = Vec::with_capacity(ciphertext_modulus_log as usize); let max_level = ciphertext_modulus_log as u64; for level in 1..=max_level { // detect increasing noise @@ -110,9 +109,9 @@ pub fn cache( security_level: u64, processing_unit: config::ProcessingUnit, complexity_model: Arc, + ciphertext_modulus_log: u32, ) -> PersistDecompCache { let cache_dir: String = default_cache_dir(); - let ciphertext_modulus_log = 64; let hardware = processing_unit.br_to_string(); let path = format!("{cache_dir}/cb-decomp-{hardware}-{ciphertext_modulus_log}-{security_level}"); diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/cmux.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/cmux.rs index f8f526087..3223c0d72 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/cmux.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/cmux.rs @@ -32,8 +32,6 @@ pub fn pareto_quantities( security_level: u64, glwe_params: GlweParameters, ) -> Vec { - assert!(ciphertext_modulus_log == 64); - let variance_bsk = glwe_params.minimal_variance(ciphertext_modulus_log, security_level); let mut quantities = Vec::with_capacity(ciphertext_modulus_log as usize); @@ -128,11 +126,12 @@ pub fn cache( security_level: u64, processing_unit: config::ProcessingUnit, complexity_model: Arc, + ciphertext_modulus_log: u32, ) -> PersistDecompCache { let cache_dir: String = default_cache_dir(); - let ciphertext_modulus_log = 64; let hardware = processing_unit.br_to_string(); - let path = format!("{cache_dir}/cmux-decomp-{hardware}-64-{security_level}"); + let path = + format!("{cache_dir}/cmux-decomp-{hardware}-{ciphertext_modulus_log}-{security_level}"); let function = move |glwe_params: GlweParameters| { pareto_quantities( diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/keyswitch.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/keyswitch.rs index d80e3cdc2..750722ff6 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/keyswitch.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/keyswitch.rs @@ -33,10 +33,9 @@ pub fn pareto_quantities( security_level: u64, internal_dim: u64, ) -> Vec { - assert!(ciphertext_modulus_log == 64); let variance_ksk = minimal_variance_lwe(internal_dim, ciphertext_modulus_log, security_level); - let mut quantities = Vec::with_capacity(64); + let mut quantities = Vec::with_capacity(ciphertext_modulus_log as usize); let mut increasing_complexity_slope = 0.0; let mut decreasing_variance = f64::INFINITY; let mut counting_no_progress = 0; @@ -131,11 +130,12 @@ pub fn cache( security_level: u64, processing_unit: config::ProcessingUnit, complexity_model: Arc, + ciphertext_modulus_log: u32, ) -> PersistDecompCache { let cache_dir: String = default_cache_dir(); - let ciphertext_modulus_log = 64; let hardware = processing_unit.ks_to_string(); - let path = format!("{cache_dir}/ks-decomp-{hardware}-64-{security_level}"); + let path = + format!("{cache_dir}/ks-decomp-{hardware}-{ciphertext_modulus_log}-{security_level}"); let function = move |internal_dim: u64| { pareto_quantities( diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/mod.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/mod.rs index e6e2e6c43..da1b097b2 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/mod.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/mod.rs @@ -31,12 +31,14 @@ pub fn cache( processing_unit: config::ProcessingUnit, complexity_model: Option>, cache_on_disk: bool, + ciphertext_modulus_log: u32, ) -> PersistDecompCaches { PersistDecompCaches::new( security_level, processing_unit, complexity_model, cache_on_disk, + ciphertext_modulus_log, ) } @@ -46,14 +48,35 @@ impl PersistDecompCaches { processing_unit: config::ProcessingUnit, complexity_model: Option>, cache_on_disk: bool, + ciphertext_modulus_log: u32, ) -> Self { let complexity_model = complexity_model.unwrap_or_else(|| processing_unit.complexity_model()); let res = Self { - ks: keyswitch::cache(security_level, processing_unit, complexity_model.clone()), - cmux: cmux::cache(security_level, processing_unit, complexity_model.clone()), - pp: pp_switch::cache(security_level, processing_unit, complexity_model.clone()), - cb: circuit_bootstrap::cache(security_level, processing_unit, complexity_model), + ks: keyswitch::cache( + security_level, + processing_unit, + complexity_model.clone(), + ciphertext_modulus_log, + ), + cmux: cmux::cache( + security_level, + processing_unit, + complexity_model.clone(), + ciphertext_modulus_log, + ), + pp: pp_switch::cache( + security_level, + processing_unit, + complexity_model.clone(), + ciphertext_modulus_log, + ), + cb: circuit_bootstrap::cache( + security_level, + processing_unit, + complexity_model, + ciphertext_modulus_log, + ), cache_on_disk, }; if cache_on_disk { diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/pp_switch.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/pp_switch.rs index 7694903f9..de3643b06 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/pp_switch.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/decomposition/pp_switch.rs @@ -35,7 +35,7 @@ pub fn pareto_quantities( glwe_params: GlweParameters, ) -> Vec { let variance_bsk = glwe_params.minimal_variance(ciphertext_modulus_log, security_level); - let mut quantities = Vec::with_capacity(64); + let mut quantities = Vec::with_capacity(ciphertext_modulus_log as usize); let mut increasing_complexity = 0.0; let mut decreasing_variance = f64::INFINITY; let mut counting_no_progress = 0; @@ -110,11 +110,12 @@ pub fn cache( security_level: u64, processing_unit: config::ProcessingUnit, complexity_model: Arc, + ciphertext_modulus_log: u32, ) -> PersistDecompCache { let cache_dir: String = default_cache_dir(); - let ciphertext_modulus_log = 64; let hardware = processing_unit.br_to_string(); - let path = format!("{cache_dir}/pp-decomp-{hardware}-64-{security_level}"); + let path = + format!("{cache_dir}/pp-decomp-{hardware}-{ciphertext_modulus_log}-{security_level}"); let function = move |glwe_params: GlweParameters| { pareto_quantities( diff --git a/compilers/concrete-optimizer/v0-parameters/benches/benchmark.rs b/compilers/concrete-optimizer/v0-parameters/benches/benchmark.rs index b6431d7ef..55445583a 100644 --- a/compilers/concrete-optimizer/v0-parameters/benches/benchmark.rs +++ b/compilers/concrete-optimizer/v0-parameters/benches/benchmark.rs @@ -18,6 +18,7 @@ fn v0_pbs_optimization(c: &mut Criterion) { wop_pbs: false, simulate_dag: false, cache_on_disk: true, + ciphertext_modulus_log: 64, }; c.bench_function("v0 PBS table generation", |b| { @@ -42,6 +43,7 @@ fn v0_pbs_optimization_simulate_graph(c: &mut Criterion) { wop_pbs: false, simulate_dag: true, cache_on_disk: true, + ciphertext_modulus_log: 64, }; c.bench_function("v0 PBS simulate dag table generation", |b| { @@ -66,6 +68,7 @@ fn v0_wop_pbs_optimization(c: &mut Criterion) { wop_pbs: true, simulate_dag: false, cache_on_disk: true, + ciphertext_modulus_log: 64, }; c.bench_function("v0 WoP-PBS table generation", |b| { diff --git a/compilers/concrete-optimizer/v0-parameters/src/lib.rs b/compilers/concrete-optimizer/v0-parameters/src/lib.rs index a42b4dd10..a6d51b61d 100644 --- a/compilers/concrete-optimizer/v0-parameters/src/lib.rs +++ b/compilers/concrete-optimizer/v0-parameters/src/lib.rs @@ -86,6 +86,9 @@ pub struct Args { #[clap(long, default_value_t = true)] pub cache_on_disk: bool, + + #[clap(long, default_value_t = 64)] + pub ciphertext_modulus_log: u32, } pub fn all_results(args: &Args) -> Vec>> { @@ -111,11 +114,17 @@ pub fn all_results(args: &Args) -> Vec>> { let config = Config { security_level, maximum_acceptable_error_probability, - ciphertext_modulus_log: 64, + ciphertext_modulus_log: args.ciphertext_modulus_log, complexity_model: &CpuComplexity::default(), }; - let cache = decomposition::cache(security_level, processing_unit, None, cache_on_disk); + let cache = decomposition::cache( + security_level, + processing_unit, + None, + cache_on_disk, + args.ciphertext_modulus_log, + ); precisions_iter .map(|precision| { @@ -277,6 +286,7 @@ mod tests { wop_pbs: false, simulate_dag, cache_on_disk: true, + ciphertext_modulus_log: 64, }; let mut actual_output = Vec::::new(); @@ -319,6 +329,7 @@ mod tests { wop_pbs: true, simulate_dag: false, cache_on_disk: true, + ciphertext_modulus_log: 64, }; let mut actual_output = Vec::::new();