poulpy/poulpy-schemes/benches/circuit_bootstrapping.rs
poulpy-schemes/benches/circuit_bootstrapping.rsRaw
1use std::hint::black_box;
2
3use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
4use poulpy_core::{
5 GGSWNoise, GLWEDecrypt, GLWEEncryptSk, GLWEExternalProduct, LWEEncryptSk, ScratchTakeCore,
6 layouts::{
7 Dsize, GGLWEToGGSWKeyLayout, GGSW, GGSWLayout, GGSWPreparedFactory, GLWEAutomorphismKeyLayout, GLWESecret,
8 GLWESecretPreparedFactory, LWE, LWELayout, LWESecret,
9 },
10};
11#[cfg(target_arch = "x86_64")]
12use poulpy_cpu_avx::FFT64Avx;
13#[cfg(not(target_arch = "x86_64"))]
14use poulpy_cpu_ref::FFT64Ref;
15
16use poulpy_hal::{
17 api::{ModuleN, ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxRotateInplace},
18 layouts::{Backend, Module, Scratch, ScratchOwned},
19 source::Source,
20};
21use poulpy_schemes::bin_fhe::{
22 blind_rotation::{
23 BlindRotationAlgo, BlindRotationKey, BlindRotationKeyFactory, BlindRotationKeyInfos, BlindRotationKeyLayout, CGGI,
24 },
25 circuit_bootstrapping::{
26 CircuitBootstrappingKey, CircuitBootstrappingKeyEncryptSk, CircuitBootstrappingKeyLayout,
27 CircuitBootstrappingKeyPrepared, CircuitBootstrappingKeyPreparedFactory, CirtuitBootstrappingExecute,
28 },
29};
30
31pub fn benc_circuit_bootstrapping<BE: Backend, BRA: BlindRotationAlgo>(c: &mut Criterion, label: &str)
32where
33 Module<BE>: ModuleNew<BE>
34 + ModuleN
35 + GLWESecretPreparedFactory<BE>
36 + GLWEExternalProduct<BE>
37 + GLWEDecrypt<BE>
38 + LWEEncryptSk<BE>
39 + CircuitBootstrappingKeyEncryptSk<BRA, BE>
40 + CircuitBootstrappingKeyPreparedFactory<BRA, BE>
41 + CirtuitBootstrappingExecute<BRA, BE>
42 + GGSWPreparedFactory<BE>
43 + GGSWNoise<BE>
44 + GLWEEncryptSk<BE>
45 + VecZnxRotateInplace<BE>,
46 BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>, // TODO find a way to remove this bound or move it to CBT KEY
47 ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
48 Scratch<BE>: ScratchTakeCore<BE>,
49{
50 let group_name: String = format!("circuit_bootstrapping::{label}");
51
52 let mut group = c.benchmark_group(group_name);
53
54 struct Params {
55 name: String,
56 extension_factor: usize,
57 k_pt: usize,
58 block_size: usize,
59 lwe_infos: LWELayout,
60 ggsw_infos: GGSWLayout,
61 cbt_infos: CircuitBootstrappingKeyLayout,
62 }
63
64 fn runner<BE: Backend, BRA: BlindRotationAlgo>(params: &Params) -> impl FnMut()
65 where
66 Module<BE>: ModuleNew<BE>
67 + ModuleN
68 + GLWESecretPreparedFactory<BE>
69 + GLWEExternalProduct<BE>
70 + GLWEDecrypt<BE>
71 + LWEEncryptSk<BE>
72 + CircuitBootstrappingKeyEncryptSk<BRA, BE>
73 + CircuitBootstrappingKeyPreparedFactory<BRA, BE>
74 + CirtuitBootstrappingExecute<BRA, BE>
75 + GGSWPreparedFactory<BE>
76 + GGSWNoise<BE>
77 + GLWEEncryptSk<BE>
78 + VecZnxRotateInplace<BE>,
79 BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>, /* TODO find a way to remove this bound or move it to CBT KEY */
80 ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
81 Scratch<BE>: ScratchTakeCore<BE>,
82 {
83 // Scratch space (4MB)
84 let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(1 << 22);
85
86 let n_glwe: poulpy_core::layouts::Degree = params.cbt_infos.layout_brk.n_glwe();
87 let n_lwe: poulpy_core::layouts::Degree = params.cbt_infos.layout_brk.n_lwe();
88 let rank: poulpy_core::layouts::Rank = params.cbt_infos.layout_brk.rank;
89
90 let module: Module<BE> = Module::<BE>::new(n_glwe.as_u32() as u64);
91
92 let mut source_xs: Source = Source::new([1u8; 32]);
93 let mut source_xa: Source = Source::new([1u8; 32]);
94 let mut source_xe: Source = Source::new([1u8; 32]);
95
96 let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe);
97 sk_lwe.fill_binary_block(params.block_size, &mut source_xs);
98 sk_lwe.fill_zero();
99
100 let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n_glwe, rank);
101 sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
102
103 let ct_lwe: LWE<Vec<u8>> = LWE::alloc_from_infos(¶ms.lwe_infos);
104
105 // Circuit bootstrapping evaluation key
106 let mut cbt_key: CircuitBootstrappingKey<Vec<u8>, BRA> = CircuitBootstrappingKey::alloc_from_infos(¶ms.cbt_infos);
107 cbt_key.encrypt_sk(
108 &module,
109 &sk_lwe,
110 &sk_glwe,
111 &mut source_xa,
112 &mut source_xe,
113 scratch.borrow(),
114 );
115
116 let mut res: GGSW<Vec<u8>> = GGSW::alloc_from_infos(¶ms.ggsw_infos);
117 let mut cbt_prepared: CircuitBootstrappingKeyPrepared<Vec<u8>, BRA, BE> =
118 CircuitBootstrappingKeyPrepared::alloc_from_infos(&module, ¶ms.cbt_infos);
119 cbt_prepared.prepare(&module, &cbt_key, scratch.borrow());
120 move || {
121 cbt_prepared.execute_to_constant(
122 &module,
123 &mut res,
124 &ct_lwe,
125 params.k_pt,
126 params.extension_factor,
127 scratch.borrow(),
128 );
129 black_box(());
130 }
131 }
132
133 for params in [Params {
134 name: String::from("1-bit"),
135 extension_factor: 1,
136 k_pt: 1,
137 lwe_infos: LWELayout {
138 n: 574_u32.into(),
139 k: 13_u32.into(),
140 base2k: 13_u32.into(),
141 },
142 block_size: 7,
143 ggsw_infos: GGSWLayout {
144 n: 1024_u32.into(),
145 base2k: 13_u32.into(),
146 k: 26_u32.into(),
147 dnum: 2_u32.into(),
148 dsize: 1_u32.into(),
149 rank: 2_u32.into(),
150 },
151 cbt_infos: CircuitBootstrappingKeyLayout {
152 layout_brk: BlindRotationKeyLayout {
153 n_glwe: 1024_u32.into(),
154 n_lwe: 574_u32.into(),
155 base2k: 13_u32.into(),
156 k: 52_u32.into(),
157 dnum: 3_u32.into(),
158 rank: 2_u32.into(),
159 },
160 layout_atk: GLWEAutomorphismKeyLayout {
161 n: 1024_u32.into(),
162 base2k: 13_u32.into(),
163 k: 52_u32.into(),
164 dnum: 3_u32.into(),
165 dsize: Dsize(1),
166 rank: 2_u32.into(),
167 },
168 layout_tsk: GGLWEToGGSWKeyLayout {
169 n: 1024_u32.into(),
170 base2k: 13_u32.into(),
171 k: 52_u32.into(),
172 dnum: 3_u32.into(),
173 dsize: Dsize(1),
174 rank: 2_u32.into(),
175 },
176 },
177 }] {
178 let id: BenchmarkId = BenchmarkId::from_parameter(params.name.clone());
179 let mut runner = runner::<BE, BRA>(¶ms);
180 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
181 }
182
183 group.finish();
184}
185
186#[cfg(not(target_arch = "x86_64"))]
187fn bench_circuit_bootstrapping_cpu_ref_fft64(c: &mut Criterion) {
188 benc_circuit_bootstrapping::<FFT64Ref, CGGI>(c, "fft64_ref");
189}
190
191#[cfg(target_arch = "x86_64")]
192fn bench_circuit_bootstrapping_cpu_avx_fft64(c: &mut Criterion) {
193 benc_circuit_bootstrapping::<FFT64Avx, CGGI>(c, "fft64_avx");
194}
195
196#[cfg(target_arch = "x86_64")]
197criterion_group!(benches, bench_circuit_bootstrapping_cpu_ref_fft64, bench_circuit_bootstrapping_cpu_avx_fft64,);
198#[cfg(not(target_arch = "x86_64"))]
199criterion_group!(benches, bench_circuit_bootstrapping_cpu_ref_fft64,);
200criterion_main!(benches);