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