Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 6 additions & 0 deletions field/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ quote = {version = "1", optional = true }

[dev-dependencies]
proptest = "1"
criterion = "0.5"
rand = { workspace = true, features = ["std", "std_rng", "small_rng"] }

[[bench]]
name = "unreduced_accum"
harness = false

[features]
use_division = []
Expand Down
114 changes: 114 additions & 0 deletions field/benches/unreduced_accum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Microbenchmark: unreduced accumulation vs Montgomery-per-iteration.
//
// Two loop shapes, each over N random inputs:
// Base scalar: acc += a_i * b_i (both base field)
// Base × Ext4: acc += a_i * c_i (a base, c Ext4)
//

use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use field::baby_bear::base::BabyBearField;
use field::baby_bear::ext4::BabyBearExt4;
use field::baby_bear::unreduced::{BabyBearExt4RawProductSum, BabyBearRawProductSum};
use field::field::{Field, FieldExtension};
use rand::rngs::SmallRng;
use rand::{Rng, SeedableRng};

fn random_base(rng: &mut impl Rng) -> BabyBearField {
BabyBearField::new(rng.random_range(0..BabyBearField::ORDER))
}

fn random_ext4(rng: &mut impl Rng) -> BabyBearExt4 {
<BabyBearExt4 as FieldExtension<BabyBearField>>::from_coeffs([
random_base(rng),
random_base(rng),
random_base(rng),
random_base(rng),
])
}

fn bench_base_dot_product(c: &mut Criterion) {
let mut group = c.benchmark_group("base_dot_product");
for &log_n in &[10usize, 16, 20] {
let n = 1usize << log_n;
let mut r = SmallRng::seed_from_u64(0xC0FFEE_u64 ^ (log_n as u64));
let pairs: Vec<(BabyBearField, BabyBearField)> = (0..n)
.map(|_| (random_base(&mut r), random_base(&mut r)))
.collect();

group.bench_with_input(
BenchmarkId::new("baseline_mul_mod", log_n),
&pairs,
|b, pairs| {
b.iter(|| {
let mut acc = BabyBearField::ZERO;
for (a, b) in pairs {
let mut t = *a;
t.mul_assign(b);
acc.add_assign(&t);
}
black_box(acc)
})
},
);

group.bench_with_input(
BenchmarkId::new("unreduced_raw_product_sum", log_n),
&pairs,
|b, pairs| {
b.iter(|| {
let mut acc = BabyBearRawProductSum::ZERO;
for (a, b) in pairs {
acc.add_assign_product(*a, *b);
}
black_box(acc.finalize())
})
},
);
}
group.finish();
}

fn bench_base_times_ext4(c: &mut Criterion) {
let mut group = c.benchmark_group("base_times_ext4");
for &log_n in &[10usize, 16, 20] {
let n = 1usize << log_n;
let mut r = SmallRng::seed_from_u64(0xC0FFEE_u64 ^ (log_n as u64));
let terms: Vec<(BabyBearField, BabyBearExt4)> = (0..n)
.map(|_| (random_base(&mut r), random_ext4(&mut r)))
.collect();

group.bench_with_input(
BenchmarkId::new("baseline_mul_by_base", log_n),
&terms,
|b, terms| {
b.iter(|| {
let mut acc = BabyBearExt4::ZERO;
for (a, c) in terms {
let mut t = *c;
t.mul_assign_by_base(a);
acc.add_assign(&t);
}
black_box(acc)
})
},
);

group.bench_with_input(
BenchmarkId::new("unreduced_ext4_raw_product_sum", log_n),
&terms,
|b, terms| {
b.iter(|| {
let mut acc = BabyBearExt4RawProductSum::ZERO;
for (a, c) in terms {
acc.add_assign_base_times_ext(*a, *c);
}
black_box(acc.finalize())
})
},
);
}
group.finish();
}

criterion_group!(benches, bench_base_dot_product, bench_base_times_ext4);
criterion_main!(benches);
2 changes: 1 addition & 1 deletion field/src/baby_bear/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl BabyBearField {
let r = (1u64 << 32) % (Self::ORDER as u64);
r as u32
};
const MONT_R2: u32 = const {
pub(crate) const MONT_R2: u32 = const {
let r = (1u64 << 32) % (Self::ORDER as u64);
let r2 = (r * r) % (Self::ORDER as u64);
r2 as u32
Expand Down
3 changes: 3 additions & 0 deletions field/src/baby_bear/ext4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ impl FieldExtension<BabyBearField> for BabyBearExt4 {

type Coeffs = [BabyBearField; 4];

#[cfg(not(target_arch = "riscv32"))]
type Unreduced = crate::baby_bear::unreduced::BabyBearExt4RawProductSum;

#[cfg_attr(not(feature = "no_inline"), inline(always))]
fn into_coeffs(self) -> Self::Coeffs {
[self.c0.c0, self.c0.c1, self.c1.c0, self.c1.c1]
Expand Down
3 changes: 3 additions & 0 deletions field/src/baby_bear/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ pub mod ext2;
pub mod ext4;
pub mod ext6;

#[cfg(not(target_arch = "riscv32"))]
pub mod unreduced;

mod ops;
Loading
Loading