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