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_backend::{FFT64Avx, FFT64Ref, FFT64Spqlios};
5use poulpy_core::layouts::{
6 Digits, GGLWEAutomorphismKeyLayout, GGLWETensorKeyLayout, GGSWCiphertext, GGSWCiphertextLayout, GLWESecret, LWECiphertext,
7 LWECiphertextLayout, LWESecret, prepared::PrepareAlloc,
8};
9use poulpy_hal::{
10 api::{
11 ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc,
12 SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism,
13 VecZnxAutomorphismInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigAllocBytes,
14 VecZnxBigAutomorphismInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy,
15 VecZnxDftAddInplace, VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxDftCopy, VecZnxFillUniform,
16 VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNegateInplace, VecZnxNormalize, VecZnxNormalizeInplace,
17 VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRotateInplaceTmpBytes, VecZnxRshInplace, VecZnxSub,
18 VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc,
19 VmpPrepare, ZnAddNormal, ZnFillUniform, ZnNormalizeInplace,
20 },
21 layouts::{Backend, Module, ScratchOwned},
22 oep::{
23 ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeMatZnxImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
24 TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxDftSliceImpl, TakeVecZnxImpl, TakeVecZnxSliceImpl,
25 },
26 source::Source,
27};
28use poulpy_schemes::tfhe::{
29 blind_rotation::{
30 BlincRotationExecute, BlindRotationAlgo, BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyEncryptSk,
31 BlindRotationKeyInfos, BlindRotationKeyLayout, BlindRotationKeyPrepared, CGGI,
32 },
33 circuit_bootstrapping::{
34 CircuitBootstrappingKey, CircuitBootstrappingKeyEncryptSk, CircuitBootstrappingKeyLayout,
35 CircuitBootstrappingKeyPrepared, CirtuitBootstrappingExecute,
36 },
37};
38
39pub fn benc_circuit_bootstrapping<B: Backend, BRA: BlindRotationAlgo>(c: &mut Criterion, label: &str)
40where
41 Module<B>: ModuleNew<B>
42 + VecZnxFillUniform
43 + VecZnxAddNormal
44 + VecZnxNormalizeInplace<B>
45 + VecZnxDftAllocBytes
46 + VecZnxBigNormalize<B>
47 + VecZnxDftApply<B>
48 + SvpApplyDftToDftInplace<B>
49 + VecZnxIdftApplyConsume<B>
50 + VecZnxNormalizeTmpBytes
51 + VecZnxSubInplace
52 + VecZnxAddInplace
53 + VecZnxNormalize<B>
54 + VecZnxSub
55 + VecZnxAddScalarInplace
56 + VecZnxAutomorphism
57 + VecZnxSwitchRing
58 + VecZnxBigAllocBytes
59 + VecZnxIdftApplyTmpA<B>
60 + SvpApplyDftToDft<B>
61 + VecZnxBigAddInplace<B>
62 + VecZnxBigAddSmallInplace<B>
63 + VecZnxBigAlloc<B>
64 + VecZnxDftAlloc<B>
65 + VecZnxBigNormalizeTmpBytes
66 + VmpPMatAlloc<B>
67 + VmpPrepare<B>
68 + SvpPrepare<B>
69 + SvpPPolAlloc<B>
70 + VmpApplyDftToDftTmpBytes
71 + VmpApplyDftToDft<B>
72 + VmpApplyDftToDftAdd<B>
73 + SvpPPolAllocBytes
74 + VecZnxRotateInplace<B>
75 + VecZnxBigAutomorphismInplace<B>
76 + VecZnxRshInplace<B>
77 + VecZnxDftCopy<B>
78 + VecZnxNegateInplace
79 + VecZnxCopy
80 + VecZnxAutomorphismInplace<B>
81 + VecZnxBigSubSmallNegateInplace<B>
82 + VecZnxRotateInplaceTmpBytes
83 + VecZnxBigAllocBytes
84 + VecZnxDftAddInplace<B>
85 + VecZnxRotate
86 + ZnFillUniform
87 + ZnAddNormal
88 + ZnNormalizeInplace<B>,
89 ScratchOwned<B>: ScratchOwnedAlloc<B> + ScratchOwnedBorrow<B>,
90 B: Backend
91 + ScratchOwnedAllocImpl<B>
92 + ScratchOwnedBorrowImpl<B>
93 + TakeVecZnxDftImpl<B>
94 + ScratchAvailableImpl<B>
95 + TakeVecZnxImpl<B>
96 + TakeScalarZnxImpl<B>
97 + TakeSvpPPolImpl<B>
98 + TakeVecZnxBigImpl<B>
99 + TakeVecZnxDftSliceImpl<B>
100 + TakeMatZnxImpl<B>
101 + TakeVecZnxSliceImpl<B>,
102 BlindRotationKey<Vec<u8>, BRA>: PrepareAlloc<B, BlindRotationKeyPrepared<Vec<u8>, BRA, B>>,
103 BlindRotationKeyPrepared<Vec<u8>, BRA, B>: BlincRotationExecute<B>,
104 BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<B>,
105{
106 let group_name: String = format!("circuit_bootstrapping::{label}");
107
108 let mut group = c.benchmark_group(group_name);
109
110 struct Params {
111 name: String,
112 extension_factor: usize,
113 k_pt: usize,
114 block_size: usize,
115 lwe_infos: LWECiphertextLayout,
116 ggsw_infos: GGSWCiphertextLayout,
117 cbt_infos: CircuitBootstrappingKeyLayout,
118 }
119
120 fn runner<B: Backend, BRA: BlindRotationAlgo>(params: &Params) -> impl FnMut()
121 where
122 Module<B>: ModuleNew<B>
123 + VecZnxFillUniform
124 + VecZnxAddNormal
125 + VecZnxNormalizeInplace<B>
126 + VecZnxDftAllocBytes
127 + VecZnxBigNormalize<B>
128 + VecZnxDftApply<B>
129 + SvpApplyDftToDftInplace<B>
130 + VecZnxIdftApplyConsume<B>
131 + VecZnxNormalizeTmpBytes
132 + VecZnxSubInplace
133 + VecZnxAddInplace
134 + VecZnxNormalize<B>
135 + VecZnxSub
136 + VecZnxAddScalarInplace
137 + VecZnxAutomorphism
138 + VecZnxSwitchRing
139 + VecZnxBigAllocBytes
140 + VecZnxIdftApplyTmpA<B>
141 + SvpApplyDftToDft<B>
142 + VecZnxBigAddInplace<B>
143 + VecZnxBigAddSmallInplace<B>
144 + VecZnxBigAlloc<B>
145 + VecZnxDftAlloc<B>
146 + VecZnxBigNormalizeTmpBytes
147 + VmpPMatAlloc<B>
148 + VmpPrepare<B>
149 + SvpPrepare<B>
150 + SvpPPolAlloc<B>
151 + VmpApplyDftToDftTmpBytes
152 + VmpApplyDftToDft<B>
153 + VmpApplyDftToDftAdd<B>
154 + SvpPPolAllocBytes
155 + VecZnxRotateInplace<B>
156 + VecZnxBigAutomorphismInplace<B>
157 + VecZnxRshInplace<B>
158 + VecZnxDftCopy<B>
159 + VecZnxNegateInplace
160 + VecZnxCopy
161 + VecZnxAutomorphismInplace<B>
162 + VecZnxBigSubSmallNegateInplace<B>
163 + VecZnxRotateInplaceTmpBytes
164 + VecZnxBigAllocBytes
165 + VecZnxDftAddInplace<B>
166 + VecZnxRotate
167 + ZnFillUniform
168 + ZnAddNormal
169 + ZnNormalizeInplace<B>,
170 B: Backend
171 + ScratchOwnedAllocImpl<B>
172 + ScratchOwnedBorrowImpl<B>
173 + TakeVecZnxDftImpl<B>
174 + ScratchAvailableImpl<B>
175 + TakeVecZnxImpl<B>
176 + TakeScalarZnxImpl<B>
177 + TakeSvpPPolImpl<B>
178 + TakeVecZnxBigImpl<B>
179 + TakeVecZnxDftSliceImpl<B>
180 + TakeMatZnxImpl<B>
181 + TakeVecZnxSliceImpl<B>,
182 BlindRotationKey<Vec<u8>, BRA>: PrepareAlloc<B, BlindRotationKeyPrepared<Vec<u8>, BRA, B>>,
183 BlindRotationKeyPrepared<Vec<u8>, BRA, B>: BlincRotationExecute<B>,
184 BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<B>,
185 {
186 // Scratch space (4MB)
187 let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(1 << 22);
188
189 let n_glwe: poulpy_core::layouts::Degree = params.cbt_infos.layout_brk.n_glwe();
190 let n_lwe: poulpy_core::layouts::Degree = params.cbt_infos.layout_brk.n_lwe();
191 let rank: poulpy_core::layouts::Rank = params.cbt_infos.layout_brk.rank;
192
193 let module: Module<B> = Module::<B>::new(n_glwe.as_u32() as u64);
194
195 let mut source_xs: Source = Source::new([1u8; 32]);
196 let mut source_xa: Source = Source::new([1u8; 32]);
197 let mut source_xe: Source = Source::new([1u8; 32]);
198
199 let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe);
200 sk_lwe.fill_binary_block(params.block_size, &mut source_xs);
201 sk_lwe.fill_zero();
202
203 let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n_glwe, rank);
204 sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
205
206 let ct_lwe: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(¶ms.lwe_infos);
207
208 // Circuit bootstrapping evaluation key
209 let cbt_key: CircuitBootstrappingKey<Vec<u8>, BRA> = CircuitBootstrappingKey::encrypt_sk(
210 &module,
211 &sk_lwe,
212 &sk_glwe,
213 ¶ms.cbt_infos,
214 &mut source_xa,
215 &mut source_xe,
216 scratch.borrow(),
217 );
218
219 let mut res: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(¶ms.ggsw_infos);
220 let cbt_prepared: CircuitBootstrappingKeyPrepared<Vec<u8>, BRA, B> = cbt_key.prepare_alloc(&module, scratch.borrow());
221
222 move || {
223 cbt_prepared.execute_to_constant(
224 &module,
225 &mut res,
226 &ct_lwe,
227 params.k_pt,
228 params.extension_factor,
229 scratch.borrow(),
230 );
231 black_box(());
232 }
233 }
234
235 for params in [Params {
236 name: String::from("1-bit"),
237 extension_factor: 1,
238 k_pt: 1,
239 lwe_infos: LWECiphertextLayout {
240 n: 574_u32.into(),
241 k: 13_u32.into(),
242 base2k: 13_u32.into(),
243 },
244 block_size: 7,
245 ggsw_infos: GGSWCiphertextLayout {
246 n: 1024_u32.into(),
247 base2k: 13_u32.into(),
248 k: 26_u32.into(),
249 rows: 2_u32.into(),
250 digits: 1_u32.into(),
251 rank: 2_u32.into(),
252 },
253 cbt_infos: CircuitBootstrappingKeyLayout {
254 layout_brk: BlindRotationKeyLayout {
255 n_glwe: 1024_u32.into(),
256 n_lwe: 574_u32.into(),
257 base2k: 13_u32.into(),
258 k: 52_u32.into(),
259 rows: 3_u32.into(),
260 rank: 2_u32.into(),
261 },
262 layout_atk: GGLWEAutomorphismKeyLayout {
263 n: 1024_u32.into(),
264 base2k: 13_u32.into(),
265 k: 52_u32.into(),
266 rows: 3_u32.into(),
267 digits: Digits(1),
268 rank: 2_u32.into(),
269 },
270 layout_tsk: GGLWETensorKeyLayout {
271 n: 1024_u32.into(),
272 base2k: 13_u32.into(),
273 k: 52_u32.into(),
274 rows: 3_u32.into(),
275 digits: Digits(1),
276 rank: 2_u32.into(),
277 },
278 },
279 }] {
280 let id: BenchmarkId = BenchmarkId::from_parameter(params.name.clone());
281 let mut runner = runner::<B, BRA>(¶ms);
282 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
283 }
284
285 group.finish();
286}
287
288fn bench_circuit_bootstrapping_cpu_ref_fft64(c: &mut Criterion) {
289 benc_circuit_bootstrapping::<FFT64Ref, CGGI>(c, "fft64_ref");
290}
291
292fn bench_circuit_bootstrapping_cpu_avx_fft64(c: &mut Criterion) {
293 benc_circuit_bootstrapping::<FFT64Avx, CGGI>(c, "fft64_avx");
294}
295
296fn bench_circuit_bootstrapping_cpu_spqlios_fft64(c: &mut Criterion) {
297 benc_circuit_bootstrapping::<FFT64Spqlios, CGGI>(c, "fft64_spqlios");
298}
299
300criterion_group!(
301 benches,
302 bench_circuit_bootstrapping_cpu_ref_fft64,
303 bench_circuit_bootstrapping_cpu_avx_fft64,
304 bench_circuit_bootstrapping_cpu_spqlios_fft64,
305);
306
307criterion_main!(benches);