Skip to content

Commit 4b6e92b

Browse files
committed
feat(core): add common mask
1 parent 05b1c9a commit 4b6e92b

46 files changed

Lines changed: 8542 additions & 11 deletions

Some content is hidden

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

Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1783,6 +1783,13 @@ bench_boolean: install_rs_check_toolchain
17831783
--bench boolean \
17841784
--features=boolean,internal-keycache -p tfhe-benchmark
17851785

1786+
.PHONY: bench_common_mask # Run benchmarks for CM-PBS
1787+
bench_common_mask: install_rs_check_toolchain
1788+
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_CHECK_TOOLCHAIN) bench \
1789+
--bench cm-bench \
1790+
--features=experimental -p tfhe-benchmark
1791+
1792+
17861793
.PHONY: bench_ks # Run benchmarks for keyswitch
17871794
bench_ks: install_rs_check_toolchain
17881795
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
@@ -54,6 +54,7 @@ internal-keycache = ["tfhe/internal-keycache"]
5454
avx512 = ["tfhe/avx512"]
5555
pbs-stats = ["tfhe/pbs-stats"]
5656
zk-pok = ["tfhe/zk-pok", "dep:tfhe-zk-pok"]
57+
experimental = ["tfhe/experimental"]
5758

5859
[[bench]]
5960
name = "boolean"
@@ -230,3 +231,9 @@ required-features = ["integer", "internal-keycache"]
230231
name = "wasm_benchmarks_parser"
231232
path = "src/bin/wasm_benchmarks_parser.rs"
232233
required-features = ["shortint", "internal-keycache"]
234+
235+
[[bench]]
236+
name = "cm-bench"
237+
path = "benches/core_crypto/cm_bench.rs"
238+
harness = false
239+
required-features = ["experimental"]
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
use cm_fft64::programmable_bootstrap_cm_lwe_ciphertext;
2+
use criterion::{black_box, criterion_main, Criterion};
3+
use tfhe::core_crypto::experimental::prelude::cm_lwe_keyswitch_key_generation::allocate_and_generate_new_cm_lwe_keyswitch_key;
4+
use tfhe::core_crypto::experimental::prelude::cm_modulus_switch_noise_reduction::improve_lwe_ciphertext_modulus_switch_noise_for_binary_key_cm;
5+
use tfhe::core_crypto::experimental::prelude::*;
6+
use tfhe::core_crypto::prelude::*;
7+
8+
fn cm_bench(c: &mut Criterion) {
9+
let bench_cm_params_2_minus_64: Vec<CmApParams> = vec![
10+
CM_PARAM_2_2_MINUS_64,
11+
CM_PARAM_4_2_MINUS_64,
12+
CM_PARAM_6_2_MINUS_64,
13+
CM_PARAM_8_2_MINUS_64,
14+
CM_PARAM_10_2_MINUS_64,
15+
CM_PARAM_2_4_MINUS_64,
16+
CM_PARAM_4_4_MINUS_64,
17+
CM_PARAM_6_4_MINUS_64,
18+
CM_PARAM_8_4_MINUS_64,
19+
CM_PARAM_10_4_MINUS_64,
20+
CM_PARAM_2_6_MINUS_64,
21+
CM_PARAM_4_6_MINUS_64,
22+
CM_PARAM_6_6_MINUS_64,
23+
CM_PARAM_8_6_MINUS_64,
24+
CM_PARAM_10_6_MINUS_64,
25+
CM_PARAM_2_8_MINUS_64,
26+
CM_PARAM_4_8_MINUS_64,
27+
CM_PARAM_6_8_MINUS_64,
28+
CM_PARAM_8_8_MINUS_64,
29+
CM_PARAM_10_8_MINUS_64,
30+
];
31+
32+
cm_bench_for_pfail(c, &bench_cm_params_2_minus_64, "2^-64");
33+
34+
let bench_cm_params_2_minus_128: Vec<CmApParams> = vec![
35+
CM_PARAM_2_2_MINUS_128,
36+
CM_PARAM_4_2_MINUS_128,
37+
CM_PARAM_6_2_MINUS_128,
38+
CM_PARAM_8_2_MINUS_128,
39+
CM_PARAM_10_2_MINUS_128,
40+
CM_PARAM_2_4_MINUS_128,
41+
CM_PARAM_4_4_MINUS_128,
42+
CM_PARAM_6_4_MINUS_128,
43+
CM_PARAM_8_4_MINUS_128,
44+
CM_PARAM_10_4_MINUS_128,
45+
CM_PARAM_2_6_MINUS_128,
46+
CM_PARAM_4_6_MINUS_128,
47+
CM_PARAM_6_6_MINUS_128,
48+
CM_PARAM_8_6_MINUS_128,
49+
CM_PARAM_10_6_MINUS_128,
50+
CM_PARAM_2_8_MINUS_128,
51+
CM_PARAM_4_8_MINUS_128,
52+
CM_PARAM_6_8_MINUS_128,
53+
CM_PARAM_8_8_MINUS_128,
54+
CM_PARAM_10_8_MINUS_128,
55+
];
56+
57+
cm_bench_for_pfail(c, &bench_cm_params_2_minus_128, "2^-128");
58+
}
59+
60+
fn cm_bench_for_pfail(c: &mut Criterion, bench_cm_params: &[CmApParams], p_fail: &str) {
61+
let mut bench_group = c.benchmark_group("Common Mask Benchmarks");
62+
bench_group.sample_size(10);
63+
64+
// Create the PRNG
65+
let mut seeder = new_seeder();
66+
let seeder = seeder.as_mut();
67+
let mut encryption_generator =
68+
EncryptionRandomGenerator::<DefaultRandomGenerator>::new(seeder.seed(), seeder);
69+
let mut secret_generator = SecretRandomGenerator::<DefaultRandomGenerator>::new(seeder.seed());
70+
71+
for cm_param in bench_cm_params {
72+
let cm_dimension = cm_param.cm_dimension;
73+
74+
let ciphertext_modulus = cm_param.ciphertext_modulus;
75+
76+
let bench_name = format!(
77+
"KS-CM-PBS_p={}_w={}_pfail={p_fail}",
78+
cm_param.precision, cm_dimension.0,
79+
);
80+
81+
let lwe_noise_distribution = cm_param.lwe_noise_distribution;
82+
83+
assert_eq!(
84+
cm_param.ciphertext_modulus,
85+
CiphertextModulus::<u64>::new_native()
86+
);
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+
cm_param.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 = PlaintextList::from_container(vec![0_u64; cm_dimension.0]);
126+
127+
let ct_in = allocate_and_encrypt_new_cm_lwe_ciphertext(
128+
&big_lwe_sk,
129+
&plaintexts,
130+
lwe_noise_distribution,
131+
ciphertext_modulus,
132+
&mut encryption_generator,
133+
);
134+
135+
let mut ct_after_ks = CmLweCiphertext::new(
136+
0u64,
137+
cm_lwe_keyswitch_key.output_lwe_dimension(),
138+
cm_dimension,
139+
ciphertext_modulus,
140+
);
141+
142+
let mut ct_out = CmLweCiphertext::new(
143+
0u64,
144+
fbsk.output_lwe_dimension(),
145+
cm_dimension,
146+
ciphertext_modulus,
147+
);
148+
149+
let max_nb_zeros_n = cm_param.max_nb_zeros_n.ceil() as usize;
150+
151+
let mut encryptions_of_zero = CmLweCiphertextList::new(
152+
0,
153+
cm_param.lwe_dimension,
154+
cm_dimension,
155+
CmLweCiphertextCount(max_nb_zeros_n),
156+
ciphertext_modulus,
157+
);
158+
159+
let plaintext_list = PlaintextList::new(0, PlaintextCount(cm_dimension.0));
160+
161+
let plaintext_lists: Vec<_> = (0..max_nb_zeros_n)
162+
.map(|_| plaintext_list.clone())
163+
.collect();
164+
165+
encrypt_cm_lwe_ciphertext_list(
166+
&small_lwe_sk,
167+
&mut encryptions_of_zero,
168+
&plaintext_lists,
169+
lwe_noise_distribution,
170+
&mut encryption_generator,
171+
);
172+
173+
let log_modulus = polynomial_size.to_blind_rotation_input_modulus_log();
174+
175+
{
176+
bench_group.bench_function(&bench_name, |b| {
177+
b.iter(|| {
178+
cm_keyswitch_lwe_ciphertext(&cm_lwe_keyswitch_key, &ct_in, &mut ct_after_ks);
179+
180+
improve_lwe_ciphertext_modulus_switch_noise_for_binary_key_cm(
181+
&mut ct_after_ks,
182+
&encryptions_of_zero,
183+
cm_param.r_sigma_factor_n,
184+
cm_param.ms_bound_n,
185+
cm_param.ms_input_variance_n,
186+
log_modulus,
187+
);
188+
189+
programmable_bootstrap_cm_lwe_ciphertext(
190+
&ct_after_ks,
191+
&mut ct_out,
192+
&accumulator.as_view(),
193+
&fbsk,
194+
);
195+
196+
black_box(&mut ct_out);
197+
})
198+
});
199+
}
200+
}
201+
202+
bench_group.finish();
203+
}
204+
205+
pub fn cm_group() {
206+
let mut criterion: Criterion<_> = (Criterion::default()).configure_from_args();
207+
208+
cm_bench(&mut criterion);
209+
}
210+
211+
criterion_main!(cm_group);

0 commit comments

Comments
 (0)