poulpy/core/benches/keyswitch_glwe_fft64.rs
core/benches/keyswitch_glwe_fft64.rsRaw
1use backend::{FFT64, Module, ScratchOwned};
2use core::{AutomorphismKey, GLWECiphertext, GLWESecret, GLWESwitchingKey, Infos};
3use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
4use sampling::source::Source;
5use std::{hint::black_box, time::Duration};
6
7fn bench_keyswitch_glwe_fft64(c: &mut Criterion) {
8 let mut group = c.benchmark_group("keyswitch_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_ksk: usize,
16 digits: usize,
17 rank_in: usize,
18 rank_out: usize,
19 }
20
21 fn runner(p: Params) -> impl FnMut() {
22 let module: Module<FFT64> = Module::<FFT64>::new(1 << p.log_n);
23
24 let basek: usize = p.basek;
25 let k_rlwe_in: usize = p.k_ct_in;
26 let k_rlwe_out: usize = p.k_ct_out;
27 let k_grlwe: usize = p.k_ksk;
28 let rank_in: usize = p.rank_in;
29 let rank_out: usize = p.rank_out;
30 let digits: usize = p.digits;
31
32 let rows: usize = (p.k_ct_in + (p.basek * digits) - 1) / (p.basek * digits);
33 let sigma: f64 = 3.2;
34
35 let mut ksk: AutomorphismKey<Vec<u8>, FFT64> = AutomorphismKey::alloc(&module, basek, k_grlwe, rows, digits, rank_out);
36 let mut ct_in: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&module, basek, k_rlwe_in, rank_in);
37 let mut ct_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&module, basek, k_rlwe_out, rank_out);
38
39 let mut scratch = ScratchOwned::new(
40 GLWESwitchingKey::encrypt_sk_scratch_space(&module, basek, ksk.k(), rank_out)
41 | GLWECiphertext::encrypt_sk_scratch_space(&module, basek, ct_in.k())
42 | GLWECiphertext::keyswitch_scratch_space(
43 &module,
44 basek,
45 ct_out.k(),
46 ct_in.k(),
47 ksk.k(),
48 digits,
49 rank_in,
50 rank_out,
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_in: GLWESecret<Vec<u8>, FFT64> = GLWESecret::alloc(&module, rank_in);
59 sk_in.fill_ternary_prob(&module, 0.5, &mut source_xs);
60
61 let mut sk_out: GLWESecret<Vec<u8>, FFT64> = GLWESecret::alloc(&module, rank_out);
62 sk_out.fill_ternary_prob(&module, 0.5, &mut source_xs);
63
64 ksk.generate_from_sk(
65 &module,
66 -1,
67 &sk_in,
68 &mut source_xa,
69 &mut source_xe,
70 sigma,
71 scratch.borrow(),
72 );
73
74 ct_in.encrypt_zero_sk(
75 &module,
76 &sk_in,
77 &mut source_xa,
78 &mut source_xe,
79 sigma,
80 scratch.borrow(),
81 );
82
83 move || {
84 black_box(ct_out.automorphism(&module, &ct_in, &ksk, scratch.borrow()));
85 }
86 }
87
88 let digits: usize = 1;
89 let basek: usize = 19;
90
91 let params_set: Vec<Params> = vec![Params {
92 log_n: 15,
93 basek: basek,
94 k_ct_in: 874 - digits * basek,
95 k_ct_out: 874 - digits * basek,
96 k_ksk: 874,
97 digits: digits,
98 rank_in: 1,
99 rank_out: 1,
100 }];
101
102 for params in params_set {
103 let id = BenchmarkId::new("KEYSWITCH_GLWE_FFT64", "");
104 let mut runner = runner(params);
105 group.sample_size(500);
106 group.measurement_time(Duration::from_secs(40));
107 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
108 }
109
110 group.finish();
111}
112
113fn bench_keyswitch_glwe_inplace_fft64(c: &mut Criterion) {
114 let mut group = c.benchmark_group("keyswitch_glwe_inplace_fft64");
115
116 struct Params {
117 log_n: usize,
118 basek: usize,
119 k_ct: usize,
120 k_ksk: usize,
121 rank: usize,
122 }
123
124 fn runner(p: Params) -> impl FnMut() {
125 let module: Module<FFT64> = Module::<FFT64>::new(1 << p.log_n);
126
127 let basek: usize = p.basek;
128 let k_ct: usize = p.k_ct;
129 let k_ksk: usize = p.k_ksk;
130 let rank: usize = p.rank;
131 let digits: usize = 1;
132
133 let rows: usize = (p.k_ct + p.basek - 1) / p.basek;
134 let sigma: f64 = 3.2;
135
136 let mut ksk: GLWESwitchingKey<Vec<u8>, FFT64> = GLWESwitchingKey::alloc(&module, basek, k_ksk, rows, digits, rank, rank);
137 let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&module, basek, k_ct, rank);
138
139 let mut scratch = ScratchOwned::new(
140 GLWESwitchingKey::encrypt_sk_scratch_space(&module, basek, ksk.k(), rank)
141 | GLWECiphertext::encrypt_sk_scratch_space(&module, basek, ct.k())
142 | GLWECiphertext::keyswitch_inplace_scratch_space(&module, basek, ct.k(), ksk.k(), digits, rank),
143 );
144
145 let mut source_xs: Source = Source::new([0u8; 32]);
146 let mut source_xe: Source = Source::new([0u8; 32]);
147 let mut source_xa: Source = Source::new([0u8; 32]);
148
149 let mut sk_in: GLWESecret<Vec<u8>, FFT64> = GLWESecret::alloc(&module, rank);
150 sk_in.fill_ternary_prob(&&module, 0.5, &mut source_xs);
151
152 let mut sk_out: GLWESecret<Vec<u8>, FFT64> = GLWESecret::alloc(&module, rank);
153 sk_out.fill_ternary_prob(&&module, 0.5, &mut source_xs);
154
155 ksk.generate_from_sk(
156 &module,
157 &sk_in,
158 &sk_out,
159 &mut source_xa,
160 &mut source_xe,
161 sigma,
162 scratch.borrow(),
163 );
164
165 ct.encrypt_zero_sk(
166 &module,
167 &sk_in,
168 &mut source_xa,
169 &mut source_xe,
170 sigma,
171 scratch.borrow(),
172 );
173
174 move || {
175 black_box(ct.keyswitch_inplace(&module, &ksk, scratch.borrow()));
176 }
177 }
178
179 let params_set: Vec<Params> = vec![Params {
180 log_n: 9,
181 basek: 18,
182 k_ct: 27,
183 k_ksk: 27,
184 rank: 1,
185 }];
186
187 for params in params_set {
188 let id = BenchmarkId::new("KEYSWITCH_GLWE_INPLACE_FFT64", "");
189 let mut runner = runner(params);
190 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
191 }
192
193 group.finish();
194}
195
196criterion_group!(
197 benches,
198 bench_keyswitch_glwe_fft64,
199 bench_keyswitch_glwe_inplace_fft64
200);
201criterion_main!(benches);