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