poulpy/poulpy-core/benches/external_product_glwe_fft64.rs
poulpy-core/benches/external_product_glwe_fft64.rsRaw
1use poulpy_core::layouts::{
2 Base2K, Degree, Dnum, Dsize, GGSW, GGSWLayout, GLWE, GLWELayout, GLWESecret, Rank, TorusPrecision,
3 prepared::{GGSWPrepared, GLWESecretPrepared},
4};
5use std::hint::black_box;
6
7use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
8
9#[cfg(all(feature = "enable-avx", target_arch = "x86_64"))]
10pub use poulpy_cpu_avx::FFT64Avx as BackendImpl;
11
12#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64")))]
13pub use poulpy_cpu_ref::FFT64Ref as BackendImpl;
14
15use poulpy_hal::{
16 api::{ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow},
17 layouts::{Module, ScalarZnx, ScratchOwned},
18 source::Source,
19};
20
21fn bench_external_product_glwe_fft64(c: &mut Criterion) {
22 let mut group = c.benchmark_group("external_product_glwe_fft64");
23
24 struct Params {
25 log_n: usize,
26 base2k: Base2K,
27 k_ct_in: TorusPrecision,
28 k_ct_out: TorusPrecision,
29 k_ggsw: TorusPrecision,
30 rank: Rank,
31 }
32
33 fn runner(p: Params) -> impl FnMut() {
34 let module: Module<BackendImpl> = Module::<BackendImpl>::new(1 << p.log_n);
35
36 let n: Degree = Degree(module.n() as u32);
37 let base2k: Base2K = p.base2k;
38 let k_ct_in: TorusPrecision = p.k_ct_in;
39 let k_ct_out: TorusPrecision = p.k_ct_out;
40 let k_ggsw: TorusPrecision = p.k_ggsw;
41 let rank: Rank = p.rank;
42 let dsize: Dsize = Dsize(1);
43
44 let dnum: Dnum = Dnum(1); //(p.k_ct_in.div_ceil(p.base2k);
45
46 let ggsw_layout: GGSWLayout = GGSWLayout {
47 n,
48 base2k,
49 k: k_ggsw,
50 dnum,
51 dsize,
52 rank,
53 };
54
55 let glwe_out_layout: GLWELayout = GLWELayout {
56 n,
57 base2k,
58 k: k_ct_out,
59 rank,
60 };
61
62 let glwe_in_layout: GLWELayout = GLWELayout {
63 n,
64 base2k,
65 k: k_ct_in,
66 rank,
67 };
68
69 let mut ct_ggsw: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_layout);
70 let mut ct_glwe_in: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_in_layout);
71 let mut ct_glwe_out: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_out_layout);
72 let pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n.into(), 1);
73
74 let mut scratch: ScratchOwned<BackendImpl> = ScratchOwned::alloc(
75 GGSW::encrypt_sk_tmp_bytes(&module, &ggsw_layout)
76 | GLWE::encrypt_sk_tmp_bytes(&module, &glwe_in_layout)
77 | GLWE::external_product_tmp_bytes(&module, &glwe_out_layout, &glwe_in_layout, &ggsw_layout),
78 );
79
80 let mut source_xs = Source::new([0u8; 32]);
81 let mut source_xe = Source::new([0u8; 32]);
82 let mut source_xa = Source::new([0u8; 32]);
83
84 let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_in_layout);
85 sk.fill_ternary_prob(0.5, &mut source_xs);
86
87 let mut sk_dft: GLWESecretPrepared<Vec<u8>, BackendImpl> = GLWESecretPrepared::alloc(&module, rank);
88 sk_dft.prepare(&module, &sk);
89
90 ct_ggsw.encrypt_sk(&module, &pt_rgsw, &sk_dft, &mut source_xa, &mut source_xe, scratch.borrow());
91
92 ct_glwe_in.encrypt_zero_sk(&module, &sk_dft, &mut source_xa, &mut source_xe, scratch.borrow());
93
94 let mut ggsw_prepared: GGSWPrepared<Vec<u8>, BackendImpl> = GGSWPrepared::alloc_from_infos(&module, &ct_ggsw);
95 ggsw_prepared.prepare(&module, &ct_ggsw, scratch.borrow());
96
97 move || {
98 ct_glwe_out.external_product(&module, &ct_glwe_in, &ggsw_prepared, scratch.borrow());
99 black_box(());
100 }
101 }
102
103 let params_set: Vec<Params> = vec![Params {
104 log_n: 11,
105 base2k: 22_u32.into(),
106 k_ct_in: 44_u32.into(),
107 k_ct_out: 44_u32.into(),
108 k_ggsw: 54_u32.into(),
109 rank: 1_u32.into(),
110 }];
111
112 for params in params_set {
113 let id = BenchmarkId::new("EXTERNAL_PRODUCT_GLWE_FFT64", "");
114 let mut runner = runner(params);
115 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
116 }
117
118 group.finish();
119}
120
121fn bench_external_product_glwe_inplace_fft64(c: &mut Criterion) {
122 let mut group = c.benchmark_group("external_product_glwe_inplace_fft64");
123
124 struct Params {
125 log_n: usize,
126 base2k: Base2K,
127 k_ct: TorusPrecision,
128 k_ggsw: TorusPrecision,
129 rank: Rank,
130 }
131
132 fn runner(p: Params) -> impl FnMut() {
133 let module: Module<BackendImpl> = Module::<BackendImpl>::new(1 << p.log_n);
134
135 let n: Degree = Degree(module.n() as u32);
136 let base2k: Base2K = p.base2k;
137 let k_glwe: TorusPrecision = p.k_ct;
138 let k_ggsw: TorusPrecision = p.k_ggsw;
139 let rank: Rank = p.rank;
140 let dsize: Dsize = Dsize(1);
141
142 let dnum: Dnum = p.k_ct.div_ceil(p.base2k).into();
143
144 let ggsw_layout: GGSWLayout = GGSWLayout {
145 n,
146 base2k,
147 k: k_ggsw,
148 dnum,
149 dsize,
150 rank,
151 };
152
153 let glwe_layout: GLWELayout = GLWELayout {
154 n,
155 base2k,
156 k: k_glwe,
157 rank,
158 };
159
160 let mut ct_ggsw: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_layout);
161 let mut ct_glwe: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_layout);
162 let pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n.into(), 1);
163
164 let mut scratch: ScratchOwned<BackendImpl> = ScratchOwned::alloc(
165 GGSW::encrypt_sk_tmp_bytes(&module, &ggsw_layout)
166 | GLWE::encrypt_sk_tmp_bytes(&module, &glwe_layout)
167 | GLWE::external_product_tmp_bytes(&module, &glwe_layout, &glwe_layout, &ggsw_layout),
168 );
169
170 let mut source_xs: Source = Source::new([0u8; 32]);
171 let mut source_xe: Source = Source::new([0u8; 32]);
172 let mut source_xa: Source = Source::new([0u8; 32]);
173
174 let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_layout);
175 sk.fill_ternary_prob(0.5, &mut source_xs);
176
177 let mut sk_dft: GLWESecretPrepared<Vec<u8>, BackendImpl> = GLWESecretPrepared::alloc(&module, rank);
178 sk_dft.prepare(&module, &sk);
179
180 ct_ggsw.encrypt_sk(&module, &pt_rgsw, &sk_dft, &mut source_xa, &mut source_xe, scratch.borrow());
181
182 ct_glwe.encrypt_zero_sk(&module, &sk_dft, &mut source_xa, &mut source_xe, scratch.borrow());
183
184 let mut ggsw_prepared: GGSWPrepared<Vec<u8>, BackendImpl> = GGSWPrepared::alloc_from_infos(&module, &ct_ggsw);
185 ggsw_prepared.prepare(&module, &ct_ggsw, scratch.borrow());
186 move || {
187 let scratch_borrow = scratch.borrow();
188 ct_glwe.external_product_inplace(&module, &ggsw_prepared, scratch_borrow);
189 black_box(());
190 }
191 }
192
193 let params_set: Vec<Params> = vec![Params {
194 log_n: 12,
195 base2k: 18_u32.into(),
196 k_ct: 54_u32.into(),
197 k_ggsw: 54_u32.into(),
198 rank: 1_u32.into(),
199 }];
200
201 for params in params_set {
202 let id = BenchmarkId::new("EXTERNAL_PRODUCT_GLWE_INPLACE_FFT64", "");
203 let mut runner = runner(params);
204 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
205 }
206
207 group.finish();
208}
209
210criterion_group!(
211 benches,
212 bench_external_product_glwe_fft64,
213 bench_external_product_glwe_inplace_fft64
214);
215criterion_main!(benches);