Skip to content

Instantly share code, notes, and snippets.

@bantic
Last active February 13, 2019 17:07
Show Gist options
  • Save bantic/59a11b75d736ccef3285593a7a2c9aa6 to your computer and use it in GitHub Desktop.
Save bantic/59a11b75d736ccef3285593a7a2c9aa6 to your computer and use it in GitHub Desktop.
Pythagorean triple calculations with and without Rayon in Rust, with benchmarks
Running target/release/deps/my_benchmark-1e021f1c2b2dab07
find 840 without rayon time: [1.0903 us 1.0999 us 1.1105 us]
change: [-2.0415% -0.5086% +1.4270%] (p = 0.56 > 0.05)
No change in performance detected.
Found 8 outliers among 100 measurements (8.00%)
1 (1.00%) high mild
7 (7.00%) high severe
find 840 with rayon time: [60.429 us 60.908 us 61.477 us]
change: [-6.5691% -3.5264% -0.1220%] (p = 0.04 < 0.05)
Change within noise threshold.
Found 16 outliers among 100 measurements (16.00%)
4 (4.00%) high mild
12 (12.00%) high severe
find 30000 without rayon
time: [26.699 us 27.310 us 28.081 us]
change: [-3.4223% -1.6239% +0.2674%] (p = 0.08 > 0.05)
No change in performance detected.
Found 10 outliers among 100 measurements (10.00%)
5 (5.00%) high mild
5 (5.00%) high severe
find 30000 with rayon time: [238.39 us 243.89 us 249.50 us]
change: [+7.6380% +9.6319% +11.609%] (p = 0.00 < 0.05)
Performance has regressed.
use pythagorean_triplet::{find, find_with_rayon};
#[macro_use]
extern crate criterion;
use criterion::Criterion;
fn criterion_benchmark_840(c: &mut Criterion) {
c.bench_function("find 840 without rayon", |b| b.iter(|| find(840)));
c.bench_function("find 840 with rayon", |b| b.iter(|| find_with_rayon(840)));
}
fn criterion_benchmark_30000(c: &mut Criterion) {
c.bench_function("find 30000 without rayon", |b| b.iter(|| find(30000)));
c.bench_function("find 30000 with rayon", |b| {
b.iter(|| find_with_rayon(30000))
});
}
criterion_group!(bench_840, criterion_benchmark_840,);
criterion_group!(bench_30000, criterion_benchmark_30000,);
criterion_main!(bench_840, bench_30000);
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use std::collections::HashSet;
pub fn find(sum: u32) -> HashSet<[u32; 3]> {
(1_u32..(sum / 3_u32))
.into_iter()
.map(|a| {
let b_plus_c = sum - a;
let b_numerator = b_plus_c.pow(2) - a.pow(2);
let b_denominator = 2 * b_plus_c;
let b = b_numerator / b_denominator;
let c = b_plus_c - b;
let ordered = a < b && b < c;
let remainder = b_numerator % b_denominator;
let is_valid = ordered && remainder == 0;
([a, b, c], is_valid)
})
.filter(|(_, is_valid)| *is_valid)
.map(|(triplet, _)| triplet)
.collect()
}
pub fn find_with_rayon(sum: u32) -> HashSet<[u32; 3]> {
(1_u32..(sum / 3_u32))
.into_par_iter()
.map(|a| {
let b_plus_c = sum - a;
let b_numerator = b_plus_c.pow(2) - a.pow(2);
let b_denominator = 2 * b_plus_c;
let b = b_numerator / b_denominator;
let c = b_plus_c - b;
let ordered = a < b && b < c;
let remainder = b_numerator % b_denominator;
let is_valid = ordered && remainder == 0;
([a, b, c], is_valid)
})
.filter(|(_, is_valid)| *is_valid)
.map(|(triplet, _)| triplet)
.collect()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment