Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ To install, add the following to your project's `Cargo.toml` file:

```toml
[dependencies]
fhe = "0.2"
fhe-traits = "0.2"
fhe = "0.2.0"
fhe-traits = "0.1.1"
```

## Minimum supported version / toolchain
Expand Down
115 changes: 59 additions & 56 deletions crates/fhe-math/benches/rq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,10 @@
)]
use criterion::measurement::WallTime;
use criterion::{BenchmarkGroup, BenchmarkId, Criterion, criterion_group, criterion_main};
use fhe_math::rq::{traits::TryConvertFrom, *};
use fhe_math::rq::{Context, Ntt, NttShoup, Poly, PowerBasis, dot_product, traits::TryConvertFrom};
use itertools::{Itertools, izip};
use rand::rng;
use std::{
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
sync::Arc,
time::Duration,
};
use std::{sync::Arc, time::Duration};

static MODULI: &[u64; 4] = &[
562949954093057,
Expand Down Expand Up @@ -42,8 +38,8 @@ macro_rules! bench_op {

for degree in DEGREE {
let ctx = Arc::new(Context::new(&MODULI[..1], *degree).unwrap());
let p = Poly::random(&ctx, Representation::Ntt, &mut rng);
let mut q = Poly::random(&ctx, Representation::Ntt, &mut rng);
let p = Poly::<Ntt>::random(&ctx, &mut rng);
let mut q = Poly::<Ntt>::random(&ctx, &mut rng);
if $vt {
unsafe { q.allow_variable_time_computations() }
}
Expand All @@ -70,8 +66,8 @@ macro_rules! bench_op_unary {

for degree in DEGREE {
let ctx = Arc::new(Context::new(&MODULI[..1], *degree).unwrap());
let p = Poly::random(&ctx, Representation::Ntt, &mut rng);
let mut q = Poly::random(&ctx, Representation::Ntt, &mut rng);
let p = Poly::<Ntt>::random(&ctx, &mut rng);
let mut q = Poly::<Ntt>::random(&ctx, &mut rng);
if $vt {
unsafe { q.allow_variable_time_computations() }
}
Expand All @@ -98,8 +94,8 @@ macro_rules! bench_op_assign {

for degree in DEGREE {
let ctx = Arc::new(Context::new(&MODULI[..1], *degree).unwrap());
let mut p = Poly::random(&ctx, Representation::Ntt, &mut rng);
let mut q = Poly::random(&ctx, Representation::Ntt, &mut rng);
let mut p = Poly::<Ntt>::random(&ctx, &mut rng);
let mut q = Poly::<Ntt>::random(&ctx, &mut rng);
if $vt {
unsafe { q.allow_variable_time_computations() }
}
Expand All @@ -116,13 +112,28 @@ macro_rules! bench_op_assign {

pub fn rq_op_benchmark(c: &mut Criterion) {
for vt in [false, true] {
bench_op!(c, "rq_add", <&Poly>::add, vt);
bench_op_assign!(c, "rq_add_assign", Poly::add_assign, vt);
bench_op!(c, "rq_sub", <&Poly>::sub, vt);
bench_op_assign!(c, "rq_sub_assign", Poly::sub_assign, vt);
bench_op!(c, "rq_mul", <&Poly>::mul, vt);
bench_op_assign!(c, "rq_mul_assign", Poly::mul_assign, vt);
bench_op_unary!(c, "rq_neg", <&Poly>::neg, vt);
bench_op!(c, "rq_add", |p, q| p + q, vt);
bench_op_assign!(
c,
"rq_add_assign",
|p: &mut Poly<Ntt>, q: &Poly<Ntt>| *p += q,
vt
);
bench_op!(c, "rq_sub", |p, q| p - q, vt);
bench_op_assign!(
c,
"rq_sub_assign",
|p: &mut Poly<Ntt>, q: &Poly<Ntt>| *p -= q,
vt
);
bench_op!(c, "rq_mul", |p, q| p * q, vt);
bench_op_assign!(
c,
"rq_mul_assign",
|p: &mut Poly<Ntt>, q: &Poly<Ntt>| *p *= q,
vt
);
bench_op_unary!(c, "rq_neg", |p: &Poly<_>| -p, vt);
}
}

Expand All @@ -133,12 +144,12 @@ pub fn rq_dot_product(c: &mut Criterion) {
for i in [1, 4] {
let ctx = Arc::new(Context::new(&MODULI[..i], *degree).unwrap());
let p_vec = (0..256)
.map(|_| Poly::random(&ctx, Representation::Ntt, &mut rng))
.map(|_| Poly::<Ntt>::random(&ctx, &mut rng))
.collect_vec();
let mut q_vec = (0..256)
.map(|_| Poly::random(&ctx, Representation::Ntt, &mut rng))
let q_vec = (0..256)
.map(|_| Poly::<Ntt>::random(&ctx, &mut rng))
.collect_vec();
let mut out = Poly::zero(&ctx, Representation::Ntt);
let mut out = Poly::<Ntt>::zero(&ctx);

group.bench_function(
BenchmarkId::from_parameter(format!("naive/{}/{}", degree, ctx.modulus().bits())),
Expand All @@ -149,9 +160,11 @@ pub fn rq_dot_product(c: &mut Criterion) {
},
);

q_vec
.iter_mut()
.for_each(|qi| qi.change_representation(Representation::NttShoup));
let q_vec_shoup = q_vec
.iter()
.cloned()
.map(Poly::<Ntt>::into_ntt_shoup)
.collect_vec();
group.bench_function(
BenchmarkId::from_parameter(format!(
"naive_shoup/{}/{}",
Expand All @@ -160,14 +173,12 @@ pub fn rq_dot_product(c: &mut Criterion) {
)),
|b| {
b.iter(|| {
izip!(p_vec.iter(), q_vec.iter()).for_each(|(pi, qi)| out += &(pi * qi))
izip!(p_vec.iter(), q_vec_shoup.iter())
.for_each(|(pi, qi)| out += &(pi * qi))
});
},
);

q_vec
.iter_mut()
.for_each(|qi| qi.change_representation(Representation::Ntt));
group.bench_function(
BenchmarkId::from_parameter(format!("opt/{}/{}", degree, ctx.modulus().bits())),
|b| {
Expand All @@ -190,9 +201,8 @@ pub fn rq_benchmark(c: &mut Criterion) {
continue;
}
let ctx = Arc::new(Context::new(&MODULI[..nmoduli], *degree).unwrap());
let mut p = Poly::random(&ctx, Representation::Ntt, &mut rng);
let mut q = Poly::random(&ctx, Representation::Ntt, &mut rng);
q.change_representation(Representation::NttShoup);
let mut p = Poly::<Ntt>::random(&ctx, &mut rng);
let q = Poly::<NttShoup>::random(&ctx, &mut rng);

group.bench_function(
BenchmarkId::new("mul_shoup", format!("{}/{}", degree, ctx.modulus().bits())),
Expand All @@ -211,54 +221,50 @@ pub fn rq_benchmark(c: &mut Criterion) {
},
);

let p_pb = Poly::<PowerBasis>::random(&ctx, &mut rng);
group.bench_function(
BenchmarkId::new(
"change_representation/PowerBasis_to_Ntt",
format!("{}/{}", degree, ctx.modulus().bits()),
),
|b| {
b.iter(|| {
unsafe {
p.override_representation(Representation::PowerBasis);
}
p.change_representation(Representation::Ntt)
let _ = p_pb.clone().into_ntt();
});
},
);

let p_ntt = Poly::<Ntt>::random(&ctx, &mut rng);
group.bench_function(
BenchmarkId::new(
"change_representation/Ntt_to_PowerBasis",
format!("{}/{}", degree, ctx.modulus().bits()),
),
|b| {
b.iter(|| {
unsafe {
p.override_representation(Representation::Ntt);
}
p.change_representation(Representation::PowerBasis)
let _ = p_ntt.clone().into_power_basis();
});
},
);

p.change_representation(Representation::Ntt);
q.change_representation(Representation::Ntt);

unsafe {
q.allow_variable_time_computations();
q.change_representation(Representation::NttShoup);
let mut q_vt = q.clone();
q_vt.allow_variable_time_computations();
let mut p_vt = p.clone();
p_vt.allow_variable_time_computations();

group.bench_function(
BenchmarkId::new(
"mul_shoup_vt",
format!("{}/{}", degree, ctx.modulus().bits()),
),
|b| {
b.iter(|| p *= &q);
b.iter(|| p_vt *= &q_vt);
},
);

p.allow_variable_time_computations();
let mut p_pb_vt = Poly::<PowerBasis>::random(&ctx, &mut rng);
p_pb_vt.allow_variable_time_computations();

group.bench_function(
BenchmarkId::new(
Expand All @@ -267,21 +273,21 @@ pub fn rq_benchmark(c: &mut Criterion) {
),
|b| {
b.iter(|| {
p.override_representation(Representation::PowerBasis);
p.change_representation(Representation::Ntt)
let _ = p_pb_vt.clone().into_ntt();
});
},
);

let mut p_ntt_vt = Poly::<Ntt>::random(&ctx, &mut rng);
p_ntt_vt.allow_variable_time_computations();
group.bench_function(
BenchmarkId::new(
"change_representation/Ntt_to_PowerBasis_vt",
format!("{}/{}", degree, ctx.modulus().bits()),
),
|b| {
b.iter(|| {
p.override_representation(Representation::Ntt);
p.change_representation(Representation::PowerBasis)
let _ = p_ntt_vt.clone().into_power_basis();
});
},
);
Expand All @@ -306,10 +312,7 @@ pub fn rq_convert_benchmark(c: &mut Criterion) {
group.bench_function(
BenchmarkId::new("try_convert_from_slice", format!("{}/{}", degree, nmoduli)),
|b| {
b.iter(|| {
Poly::try_convert_from(slice, &ctx, false, Representation::PowerBasis)
.unwrap()
});
b.iter(|| Poly::<PowerBasis>::try_convert_from(slice, &ctx, false).unwrap());
},
);
}
Expand Down
Loading
Loading