Skip to content

Commit 4fcda6f

Browse files
committed
feat(core): add common mask
1 parent d9ba1dc commit 4fcda6f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+8381
-0
lines changed

Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,6 +1667,13 @@ bench_boolean: install_rs_check_toolchain
16671667
--bench boolean \
16681668
--features=boolean,internal-keycache -p tfhe-benchmark
16691669

1670+
.PHONY: bench_common_mask # Run benchmarks for CM-PBS
1671+
bench_common_mask: install_rs_check_toolchain
1672+
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_CHECK_TOOLCHAIN) bench \
1673+
--bench cm-bench \
1674+
--features=experimental -p tfhe-benchmark
1675+
1676+
16701677
.PHONY: bench_ks # Run benchmarks for keyswitch
16711678
bench_ks: install_rs_check_toolchain
16721679
RUSTFLAGS="$(RUSTFLAGS)" __TFHE_RS_PARAM_TYPE=$(BENCH_PARAM_TYPE) __TFHE_RS_PARAMS_SET=$(BENCH_PARAMS_SET) __TFHE_RS_BENCH_TYPE=$(BENCH_TYPE) \

tfhe-benchmark/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ internal-keycache = ["tfhe/internal-keycache"]
4545
avx512 = ["tfhe/avx512"]
4646
pbs-stats = ["tfhe/pbs-stats"]
4747
zk-pok = ["tfhe/zk-pok"]
48+
experimental = ["tfhe/experimental"]
4849

4950
[[bench]]
5051
name = "boolean"
@@ -215,3 +216,9 @@ required-features = ["integer", "internal-keycache"]
215216
name = "wasm_benchmarks_parser"
216217
path = "src/bin/wasm_benchmarks_parser.rs"
217218
required-features = ["shortint", "internal-keycache"]
219+
220+
[[bench]]
221+
name = "cm-bench"
222+
path = "benches/core_crypto/cm_bench.rs"
223+
harness = false
224+
required-features = []
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
use cm_fft64::programmable_bootstrap_cm_lwe_ciphertext;
2+
use criterion::{black_box, criterion_main, Criterion};
3+
use itertools::Itertools;
4+
use tfhe::core_crypto::experimental::prelude::cm_lwe_keyswitch_key_generation::allocate_and_generate_new_cm_lwe_keyswitch_key;
5+
use tfhe::core_crypto::experimental::prelude::cm_modulus_switch_noise_reduction::improve_lwe_ciphertext_modulus_switch_noise_for_binary_key_cm;
6+
use tfhe::core_crypto::experimental::prelude::*;
7+
use tfhe::core_crypto::prelude::*;
8+
9+
fn cm_bench(c: &mut Criterion) {
10+
let bench_cm_params_2_minus_64: Vec<CmApParams> = vec![
11+
CM_PARAM_2_2_MINUS_64,
12+
CM_PARAM_4_2_MINUS_64,
13+
CM_PARAM_6_2_MINUS_64,
14+
CM_PARAM_8_2_MINUS_64,
15+
CM_PARAM_10_2_MINUS_64,
16+
CM_PARAM_2_4_MINUS_64,
17+
CM_PARAM_4_4_MINUS_64,
18+
CM_PARAM_6_4_MINUS_64,
19+
CM_PARAM_8_4_MINUS_64,
20+
CM_PARAM_10_4_MINUS_64,
21+
CM_PARAM_2_6_MINUS_64,
22+
CM_PARAM_4_6_MINUS_64,
23+
CM_PARAM_6_6_MINUS_64,
24+
CM_PARAM_8_6_MINUS_64,
25+
CM_PARAM_10_6_MINUS_64,
26+
CM_PARAM_2_8_MINUS_64,
27+
CM_PARAM_4_8_MINUS_64,
28+
CM_PARAM_6_8_MINUS_64,
29+
CM_PARAM_8_8_MINUS_64,
30+
CM_PARAM_10_8_MINUS_64,
31+
];
32+
33+
cm_bench_for_pfail(c, &bench_cm_params_2_minus_64, "2^-64");
34+
35+
let bench_cm_params_2_minus_128: Vec<CmApParams> = vec![
36+
CM_PARAM_2_2_MINUS_128,
37+
CM_PARAM_4_2_MINUS_128,
38+
CM_PARAM_6_2_MINUS_128,
39+
CM_PARAM_8_2_MINUS_128,
40+
CM_PARAM_10_2_MINUS_128,
41+
CM_PARAM_2_4_MINUS_128,
42+
CM_PARAM_4_4_MINUS_128,
43+
CM_PARAM_6_4_MINUS_128,
44+
CM_PARAM_8_4_MINUS_128,
45+
CM_PARAM_10_4_MINUS_128,
46+
CM_PARAM_2_6_MINUS_128,
47+
CM_PARAM_4_6_MINUS_128,
48+
CM_PARAM_6_6_MINUS_128,
49+
CM_PARAM_8_6_MINUS_128,
50+
CM_PARAM_10_6_MINUS_128,
51+
CM_PARAM_2_8_MINUS_128,
52+
CM_PARAM_4_8_MINUS_128,
53+
CM_PARAM_6_8_MINUS_128,
54+
CM_PARAM_8_8_MINUS_128,
55+
CM_PARAM_10_8_MINUS_128,
56+
];
57+
58+
cm_bench_for_pfail(c, &bench_cm_params_2_minus_128, "2^-128");
59+
}
60+
61+
fn cm_bench_for_pfail(c: &mut Criterion, bench_cm_params: &[CmApParams], p_fail: &str) {
62+
let mut bench_group = c.benchmark_group("Common Mask Benchmarks");
63+
bench_group.sample_size(10);
64+
65+
// Create the PRNG
66+
let mut seeder = new_seeder();
67+
let seeder = seeder.as_mut();
68+
let mut encryption_generator =
69+
EncryptionRandomGenerator::<DefaultRandomGenerator>::new(seeder.seed(), seeder);
70+
let mut secret_generator = SecretRandomGenerator::<DefaultRandomGenerator>::new(seeder.seed());
71+
72+
for cm_param in bench_cm_params {
73+
let cm_dimension = cm_param.cm_dimension;
74+
75+
let total_number = cm_dimension.0;
76+
77+
let bench_name = format!(
78+
"KS-CM-PBS_p={}_w={}_pfail={p_fail}",
79+
cm_param.precision, cm_dimension.0,
80+
);
81+
82+
let lwe_noise_distribution = DynamicDistribution::<u64>::new_gaussian_from_std_dev(
83+
StandardDev(cm_param.lwe_std_dev),
84+
);
85+
86+
let ciphertext_modulus = CiphertextModulus::<u64>::new_native();
87+
let encoding_with_padding = 1 << 63;
88+
let glwe_dimension = cm_param.glwe_dimension;
89+
let polynomial_size = cm_param.polynomial_size;
90+
91+
let msg_modulus = 1u64 << cm_param.precision;
92+
let delta = encoding_with_padding / msg_modulus;
93+
94+
let f = |x| x;
95+
96+
let accumulator = cm_generate_programmable_bootstrap_glwe_lut(
97+
polynomial_size,
98+
glwe_dimension,
99+
cm_dimension,
100+
msg_modulus.cast_into(),
101+
ciphertext_modulus,
102+
delta,
103+
f,
104+
);
105+
106+
let CmBootstrapKeys {
107+
small_lwe_sk,
108+
big_lwe_sk,
109+
bsk,
110+
fbsk,
111+
} = generate_cm_pbs_keys(cm_param, &mut encryption_generator, &mut secret_generator);
112+
drop(bsk);
113+
114+
let cm_lwe_keyswitch_key = allocate_and_generate_new_cm_lwe_keyswitch_key(
115+
&big_lwe_sk,
116+
&small_lwe_sk,
117+
cm_dimension,
118+
cm_param.base_log_ks,
119+
cm_param.level_ks,
120+
lwe_noise_distribution,
121+
ciphertext_modulus,
122+
&mut encryption_generator,
123+
);
124+
125+
let plaintexts =
126+
PlaintextList::from_container((0..cm_dimension.0).map(|_| 0).collect_vec());
127+
128+
let ct_in = allocate_and_encrypt_new_cm_lwe_ciphertext(
129+
&big_lwe_sk,
130+
&plaintexts,
131+
lwe_noise_distribution,
132+
ciphertext_modulus,
133+
&mut encryption_generator,
134+
);
135+
136+
let mut ct_after_ks = CmLweCiphertext::new(
137+
0u64,
138+
fbsk.input_lwe_dimension(),
139+
cm_dimension,
140+
ciphertext_modulus,
141+
);
142+
143+
let mut ct_out = CmLweCiphertext::new(
144+
0u64,
145+
fbsk.output_lwe_dimension(),
146+
cm_dimension,
147+
ciphertext_modulus,
148+
);
149+
150+
let max_nb_zeros_n = (cm_param.max_nb_zeros_n + 1.) as usize;
151+
152+
let mut encryptions_of_zero = CmLweCiphertextList::new(
153+
0,
154+
cm_param.lwe_dimension,
155+
cm_dimension,
156+
CmLweCiphertextCount(max_nb_zeros_n),
157+
ciphertext_modulus,
158+
);
159+
160+
let plaintext_list = PlaintextList::new(0, PlaintextCount(cm_dimension.0));
161+
162+
let plaintext_lists: Vec<_> = (0..max_nb_zeros_n)
163+
.map(|_| plaintext_list.clone())
164+
.collect();
165+
166+
encrypt_cm_lwe_ciphertext_list(
167+
&small_lwe_sk,
168+
&mut encryptions_of_zero,
169+
&plaintext_lists,
170+
lwe_noise_distribution,
171+
&mut encryption_generator,
172+
);
173+
174+
let log_modulus = polynomial_size.to_blind_rotation_input_modulus_log();
175+
176+
{
177+
let id: String = format!("{bench_name}");
178+
bench_group.bench_function(&id, |b| {
179+
b.iter(|| {
180+
(0..total_number / cm_dimension.0).for_each(|_| {
181+
cm_keyswitch_lwe_ciphertext(
182+
&cm_lwe_keyswitch_key,
183+
&ct_in,
184+
&mut ct_after_ks,
185+
);
186+
187+
improve_lwe_ciphertext_modulus_switch_noise_for_binary_key_cm(
188+
&mut ct_after_ks,
189+
&encryptions_of_zero,
190+
cm_param.r_sigma_factor_n,
191+
cm_param.ms_bound_n,
192+
cm_param.ms_input_variance_n,
193+
log_modulus,
194+
);
195+
196+
programmable_bootstrap_cm_lwe_ciphertext(
197+
&ct_after_ks,
198+
&mut ct_out,
199+
&accumulator.as_view(),
200+
&fbsk,
201+
);
202+
203+
black_box(&mut ct_out);
204+
})
205+
})
206+
});
207+
}
208+
}
209+
210+
bench_group.finish();
211+
}
212+
213+
pub fn cm_group() {
214+
let mut criterion: Criterion<_> = (Criterion::default()).configure_from_args();
215+
216+
cm_bench(&mut criterion);
217+
}
218+
219+
criterion_main!(cm_group);

0 commit comments

Comments
 (0)