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_rgsw: GGSWCiphertext<Vec<u8>, FFT64> = GGSWCiphertext::alloc(&module, basek, k_ggsw, rows, rank);
37 let mut ct_rlwe_in: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&module, basek, k_ct_in, rank);
38 let mut ct_rlwe_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, rank, ct_rgsw.size())
43 | GLWECiphertext::encrypt_sk_scratch_space(&module, ct_rlwe_in.size())
44 | GLWECiphertext::external_product_scratch_space(
45 &module,
46 ct_rlwe_out.size(),
47 ct_rlwe_in.size(),
48 ct_rgsw.size(),
49 rank,
50 ),
51 );
52
53 let mut source_xs = Source::new([0u8; 32]);
54 let mut source_xe = Source::new([0u8; 32]);
55 let mut source_xa = Source::new([0u8; 32]);
56
57 let mut sk: SecretKey<Vec<u8>> = SecretKey::alloc(&module, rank);
58 sk.fill_ternary_prob(0.5, &mut source_xs);
59 let mut sk_dft: SecretKeyFourier<Vec<u8>, FFT64> = SecretKeyFourier::alloc(&module, rank);
60 sk_dft.dft(&module, &sk);
61
62 ct_rgsw.encrypt_sk(
63 &module,
64 &pt_rgsw,
65 &sk_dft,
66 &mut source_xa,
67 &mut source_xe,
68 sigma,
69 scratch.borrow(),
70 );
71
72 ct_rlwe_in.encrypt_zero_sk(
73 &module,
74 &sk_dft,
75 &mut source_xa,
76 &mut source_xe,
77 sigma,
78 scratch.borrow(),
79 );
80
81 move || {
82 ct_rlwe_out.external_product(
83 black_box(&module),
84 black_box(&ct_rlwe_in),
85 black_box(&ct_rgsw),
86 black_box(scratch.borrow()),
87 );
88 }
89 }
90
91 let params_set: Vec<Params> = vec![Params {
92 log_n: 10,
93 basek: 7,
94 k_ct_in: 27,
95 k_ct_out: 27,
96 k_ggsw: 27,
97 rank: 1,
98 }];
99
100 for params in params_set {
101 let id = BenchmarkId::new("EXTERNAL_PRODUCT_GLWE_FFT64", "");
102 let mut runner = runner(params);
103 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
104 }
105
106 group.finish();
107}
108
109fn bench_external_product_glwe_inplace_fft64(c: &mut Criterion) {
110 let mut group = c.benchmark_group("external_product_glwe_inplace_fft64");
111
112 struct Params {
113 log_n: usize,
114 basek: usize,
115 k_ct: usize,
116 k_ggsw: usize,
117 rank: usize,
118 }
119
120 fn runner(p: Params) -> impl FnMut() {
121 let module: Module<FFT64> = Module::<FFT64>::new(1 << p.log_n);
122
123 let basek: usize = p.basek;
124 let k_glwe: usize = p.k_ct;
125 let k_ggsw: usize = p.k_ggsw;
126 let rank: usize = p.rank;
127
128 let rows: usize = (p.k_ct + p.basek - 1) / p.basek;
129 let sigma: f64 = 3.2;
130
131 let mut ct_rgsw: GGSWCiphertext<Vec<u8>, FFT64> = GGSWCiphertext::alloc(&module, basek, k_ggsw, rows, rank);
132 let mut ct_rlwe: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&module, basek, k_glwe, rank);
133 let pt_rgsw: ScalarZnx<Vec<u8>> = module.new_scalar_znx(1);
134
135 let mut scratch = ScratchOwned::new(
136 GGSWCiphertext::encrypt_sk_scratch_space(&module, rank, ct_rgsw.size())
137 | GLWECiphertext::encrypt_sk_scratch_space(&module, ct_rlwe.size())
138 | GLWECiphertext::external_product_inplace_scratch_space(&module, ct_rlwe.size(), ct_rgsw.size(), rank),
139 );
140
141 let mut source_xs = Source::new([0u8; 32]);
142 let mut source_xe = Source::new([0u8; 32]);
143 let mut source_xa = Source::new([0u8; 32]);
144
145 let mut sk: SecretKey<Vec<u8>> = SecretKey::alloc(&module, rank);
146 sk.fill_ternary_prob(0.5, &mut source_xs);
147 let mut sk_dft: SecretKeyFourier<Vec<u8>, FFT64> = SecretKeyFourier::alloc(&module, rank);
148 sk_dft.dft(&module, &sk);
149
150 ct_rgsw.encrypt_sk(
151 &module,
152 &pt_rgsw,
153 &sk_dft,
154 &mut source_xa,
155 &mut source_xe,
156 sigma,
157 scratch.borrow(),
158 );
159
160 ct_rlwe.encrypt_zero_sk(
161 &module,
162 &sk_dft,
163 &mut source_xa,
164 &mut source_xe,
165 sigma,
166 scratch.borrow(),
167 );
168
169 move || {
170 let scratch_borrow = scratch.borrow();
171 (0..687).for_each(|_| {
172 ct_rlwe.external_product_inplace(
173 black_box(&module),
174 black_box(&ct_rgsw),
175 black_box(scratch_borrow),
176 );
177 });
178 }
179 }
180
181 let params_set: Vec<Params> = vec![Params {
182 log_n: 12,
183 basek: 18,
184 k_ct: 54,
185 k_ggsw: 54,
186 rank: 1,
187 }];
188
189 for params in params_set {
190 let id = BenchmarkId::new("EXTERNAL_PRODUCT_GLWE_INPLACE_FFT64", "");
191 let mut runner = runner(params);
192 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
193 }
194
195 group.finish();
196}
197
198criterion_group!(
199 benches,
200 bench_external_product_glwe_fft64,
201 bench_external_product_glwe_inplace_fft64
202);
203criterion_main!(benches);