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