Skip to content

Commit c4a4c3c

Browse files
authored
test: use full range for floats uniform (jvdd#60)
* test: use full range for floats uniform * 🧹 formatting * tests: use SampleUniformFullRange in integration tests * bench: update benchmarks with SampleUniformFullRange * test: update int and uint with SampleUniformFullRange * fix: use correct trait * ci: skip MIPS as it is not supported on nightly anymore * 🧹 remove unused function * fix: use trait instead of removed function * :detetctive: float uniform test * ⬆️ update dev dependencies * 🧹 fix arrow2 tests for half * ⬆️ update codspeed CI action
1 parent 8d730ac commit c4a4c3c

35 files changed

+167
-118
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,12 @@ jobs:
129129
- i586-unknown-linux-gnu
130130
- aarch64-unknown-linux-gnu
131131
- armv7-unknown-linux-gnueabihf
132-
- mips-unknown-linux-gnu
133-
- mips64-unknown-linux-gnuabi64
132+
# MIPS is currently not supported anymore on nightly chains.
133+
# more information:
134+
# - https://github.com/rust-lang/compiler-team/issues/648
135+
# - https://github.com/rust-lang/rust/pull/113274
136+
# - mips-unknown-linux-gnu
137+
# - mips64-unknown-linux-gnuabi64
134138
- powerpc-unknown-linux-gnu
135139
- powerpc64-unknown-linux-gnu
136140
- riscv64gc-unknown-linux-gnu

.github/workflows/codspeed.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
- name: Build the benchmark target(s)
4444
run: cargo codspeed build --features half
4545

46-
- uses: CodSpeedHQ/action@v1
46+
- uses: CodSpeedHQ/action@v2
4747
name: Run benchmarks
4848
with:
4949
run: cargo codspeed run

Cargo.toml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ exclude = [".git*", "dev_utils/**/*", "tests/**/*"]
1414

1515

1616
[dependencies]
17-
num-traits = { version = "0.2.15", default-features = false }
18-
half = { version = "2.1.0", default-features = false, features=["num-traits"], optional = true }
17+
num-traits = { version = "0.2.17", default-features = false }
18+
half = { version = "2.3.1", default-features = false, features=["num-traits"], optional = true }
1919
ndarray = { version = "0.15.6", default-features = false, optional = true}
2020
arrow = { version = ">0", default-features = false, optional = true}
2121
arrow2 = { version = ">0.0", default-features = false, optional = true}
@@ -31,13 +31,16 @@ arrow = ["dep:arrow"]
3131
arrow2 = ["dep:arrow2"]
3232

3333
[dev-dependencies]
34-
rstest = { version = "0.16", default-features = false }
35-
rstest_reuse = { version = "0.5", default-features = false }
36-
rand = { version = "0.7.2", default-features = false }
37-
codspeed-criterion-compat = "1.1"
38-
criterion = "0.3.1"
34+
rstest = { version = "0.18.2", default-features = false }
35+
rstest_reuse = { version = "0.6", default-features = false }
36+
rand = { version = "0.8.5", default-features = false }
37+
codspeed-criterion-compat = "2.3.3"
38+
criterion = "0.5.1"
3939
dev_utils = { path = "dev_utils" }
4040

41+
[dev-dependencies.half]
42+
features = ["rand_distr"]
43+
4144

4245
[[bench]]
4346
name = "bench_f16_return_nan"

benches/bench_f16_ignore_nan.rs

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,11 @@ use argminmax::simd::{SIMDArgMinMax, NEON};
1313

1414
use half::f16;
1515

16-
fn get_random_f16_array(n: usize) -> Vec<f16> {
17-
let data = utils::get_random_array::<i16>(n, -0x7C00, 0x7C00);
18-
let data: Vec<f16> = data.iter().map(|&x| f16::from_bits(x as u16)).collect();
19-
// Replace NaNs and Infs with 0
20-
let data: Vec<f16> = data
21-
.iter()
22-
.map(|&x| {
23-
if x.is_nan() || x.is_infinite() {
24-
f16::from_bits(0)
25-
} else {
26-
x
27-
}
28-
})
29-
.collect();
30-
data
31-
}
32-
3316
// _in stands for "ignore nan"
3417

3518
fn argminmax_in_f16_random_array_long(c: &mut Criterion) {
3619
let n = config::ARRAY_LENGTH_LONG;
37-
let data: &[f16] = &get_random_f16_array(n);
20+
let data: &[f16] = &utils::SampleUniformFullRange::get_random_array(n);
3821
c.bench_function("scalar_f16_argminmax_in", |b| {
3922
b.iter(|| SCALAR::<FloatIgnoreNaN>::argminmax(black_box(data)))
4023
});

benches/bench_f16_return_nan.rs

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,11 @@ use argminmax::simd::{SIMDArgMinMax, NEON};
1313

1414
use half::f16;
1515

16-
fn get_random_f16_array(n: usize) -> Vec<f16> {
17-
let data = utils::get_random_array::<i16>(n, -0x7C00, 0x7C00);
18-
let data: Vec<f16> = data.iter().map(|&x| f16::from_bits(x as u16)).collect();
19-
// Replace NaNs and Infs with 0
20-
let data: Vec<f16> = data
21-
.iter()
22-
.map(|&x| {
23-
if x.is_nan() || x.is_infinite() {
24-
f16::from_bits(0)
25-
} else {
26-
x
27-
}
28-
})
29-
.collect();
30-
data
31-
}
32-
3316
// _rn stands for "return nan"
3417

3518
fn argminmax_rn_f16_random_array_long(c: &mut Criterion) {
3619
let n = config::ARRAY_LENGTH_LONG;
37-
let data: &[f16] = &get_random_f16_array(n);
20+
let data: &[f16] = &utils::SampleUniformFullRange::get_random_array(n);
3821
c.bench_function("scalar_f16_argminmax_rn", |b| {
3922
b.iter(|| SCALAR::<FloatReturnNaN>::argminmax(black_box(data)))
4023
});

benches/bench_f32_ignore_nan.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use argminmax::simd::{SIMDArgMinMax, NEON};
1515

1616
fn argminmax_in_f32_random_array_long(c: &mut Criterion) {
1717
let n = config::ARRAY_LENGTH_LONG;
18-
let data: &[f32] = &utils::get_random_array::<f32>(n, f32::MIN, f32::MAX);
18+
let data: &[f32] = &utils::SampleUniformFullRange::get_random_array(n);
1919
c.bench_function("scalar_f32_argminmax_in", |b| {
2020
b.iter(|| SCALAR::<FloatIgnoreNaN>::argminmax(black_box(data)))
2121
});

benches/bench_f32_return_nan.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use argminmax::simd::{SIMDArgMinMax, NEON};
1515

1616
fn argminmax_rn_f32_random_array_long(c: &mut Criterion) {
1717
let n = config::ARRAY_LENGTH_LONG;
18-
let data: &[f32] = &utils::get_random_array::<f32>(n, f32::MIN, f32::MAX);
18+
let data: &[f32] = &utils::SampleUniformFullRange::get_random_array(n);
1919
c.bench_function("scalar_f32_argminmax_rn", |b| {
2020
b.iter(|| SCALAR::<FloatReturnNaN>::argminmax(black_box(data)))
2121
});

benches/bench_f64_ignore_nan.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use argminmax::simd::{SIMDArgMinMax, NEON};
1515

1616
fn argminmax_in_f64_random_array_long(c: &mut Criterion) {
1717
let n = config::ARRAY_LENGTH_LONG;
18-
let data: &[f64] = &utils::get_random_array::<f64>(n, f64::MIN, f64::MAX);
18+
let data: &[f64] = &utils::SampleUniformFullRange::get_random_array(n);
1919
c.bench_function("scalar_f64_argminmax_in", |b| {
2020
b.iter(|| SCALAR::<FloatIgnoreNaN>::argminmax(black_box(data)))
2121
});

benches/bench_f64_return_nan.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use argminmax::simd::{SIMDArgMinMax, NEON};
1515

1616
fn argminmax_rn_f64_random_array_long(c: &mut Criterion) {
1717
let n = config::ARRAY_LENGTH_LONG;
18-
let data: &[f64] = &utils::get_random_array::<f64>(n, f64::MIN, f64::MAX);
18+
let data: &[f64] = &utils::SampleUniformFullRange::get_random_array(n);
1919
c.bench_function("scalar_f64_argminmax_rn", |b| {
2020
b.iter(|| SCALAR::<FloatReturnNaN>::argminmax(black_box(data)))
2121
});

benches/bench_i16.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use argminmax::simd::{SIMDArgMinMax, NEON};
1212

1313
fn argminmax_i16_random_array_long(c: &mut Criterion) {
1414
let n = config::ARRAY_LENGTH_LONG;
15-
let data: &[i16] = &utils::get_random_array::<i16>(n, i16::MIN, i16::MAX);
15+
let data: &[i16] = &utils::SampleUniformFullRange::get_random_array(n);
1616
c.bench_function("scalar_i16_argminmax", |b| {
1717
b.iter(|| SCALAR::argminmax(black_box(data)))
1818
});

benches/bench_i32.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use argminmax::simd::{SIMDArgMinMax, NEON};
1212

1313
fn argminmax_i32_random_array_long(c: &mut Criterion) {
1414
let n = config::ARRAY_LENGTH_LONG;
15-
let data: &[i32] = &utils::get_random_array::<i32>(n, i32::MIN, i32::MAX);
15+
let data: &[i32] = &utils::SampleUniformFullRange::get_random_array(n);
1616
c.bench_function("scalar_i32_argminmax", |b| {
1717
b.iter(|| SCALAR::argminmax(black_box(data)))
1818
});

benches/bench_i64.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use argminmax::simd::{SIMDArgMinMax, NEON};
1212

1313
fn argminmax_i64_random_array_long(c: &mut Criterion) {
1414
let n = config::ARRAY_LENGTH_LONG;
15-
let data: &[i64] = &utils::get_random_array::<i64>(n, i64::MIN, i64::MAX);
15+
let data: &[i64] = &utils::SampleUniformFullRange::get_random_array(n);
1616
c.bench_function("scalar_i64_argminmax", |b| {
1717
b.iter(|| SCALAR::argminmax(black_box(data)))
1818
});

benches/bench_i8.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use argminmax::simd::{SIMDArgMinMax, NEON};
1212

1313
fn argminmax_i8_random_array_long(c: &mut Criterion) {
1414
let n = config::ARRAY_LENGTH_LONG;
15-
let data: &[i8] = &utils::get_random_array::<i8>(n, i8::MIN, i8::MAX);
15+
let data: &[i8] = &utils::SampleUniformFullRange::get_random_array(n);
1616
c.bench_function("scalar_i8_argminmax", |b| {
1717
b.iter(|| SCALAR::argminmax(black_box(data)))
1818
});

benches/bench_u16.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use argminmax::simd::{SIMDArgMinMax, NEON};
1212

1313
fn argminmax_u16_random_array_long(c: &mut Criterion) {
1414
let n = config::ARRAY_LENGTH_LONG;
15-
let data: &[u16] = &utils::get_random_array::<u16>(n, u16::MIN, u16::MAX);
15+
let data: &[u16] = &utils::SampleUniformFullRange::get_random_array(n);
1616
c.bench_function("scalar_u16_argminmax", |b| {
1717
b.iter(|| SCALAR::argminmax(black_box(data)))
1818
});

benches/bench_u32.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use argminmax::simd::{SIMDArgMinMax, NEON};
1212

1313
fn argminmax_u32_random_array_long(c: &mut Criterion) {
1414
let n = config::ARRAY_LENGTH_LONG;
15-
let data: &[u32] = &utils::get_random_array::<u32>(n, u32::MIN, u32::MAX);
15+
let data: &[u32] = &utils::SampleUniformFullRange::get_random_array(n);
1616
c.bench_function("scalar_u32_argminmax", |b| {
1717
b.iter(|| SCALAR::argminmax(black_box(data)))
1818
});

benches/bench_u64.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use argminmax::simd::{SIMDArgMinMax, NEON};
1212

1313
fn argminmax_u64_random_array_long(c: &mut Criterion) {
1414
let n = config::ARRAY_LENGTH_LONG;
15-
let data: &[u64] = &utils::get_random_array::<u64>(n, u64::MIN, u64::MAX);
15+
let data: &[u64] = &utils::SampleUniformFullRange::get_random_array(n);
1616
c.bench_function("scalar_u64_argminmax", |b| {
1717
b.iter(|| SCALAR::argminmax(black_box(data)))
1818
});

benches/bench_u8.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use argminmax::simd::{SIMDArgMinMax, NEON};
1212

1313
fn argminmax_u8_random_array_long(c: &mut Criterion) {
1414
let n = config::ARRAY_LENGTH_LONG;
15-
let data: &[u8] = &utils::get_random_array::<u8>(n, u8::MIN, u8::MAX);
15+
let data: &[u8] = &utils::SampleUniformFullRange::get_random_array(n);
1616
c.bench_function("scalar_u8_argminmax", |b| {
1717
b.iter(|| SCALAR::argminmax(black_box(data)))
1818
});

dev_utils/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ edition = "2021"
66
description = "Shared utilities for development (tests & benchmarks)"
77

88
[dependencies]
9-
rand = { version = "0.7.2", default-features = false }
10-
rand_distr = { version = "0.2.2", default-features = false }
9+
num-traits = { version = "0.2.17", default-features = false }
10+
half = { version = "2.3.1", default-features = false, features = ["num-traits", "rand_distr"] }
11+
rand = { version = "0.8.5" }

dev_utils/src/utils.rs

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
1+
use half::f16;
2+
use num_traits::Zero;
3+
14
use std::ops::{Add, Sub};
25

6+
use rand::distributions::Uniform;
37
use rand::{thread_rng, Rng};
4-
use rand_distr::Uniform;
5-
6-
// random array that samples between min and max of T
7-
pub fn get_random_array<T>(n: usize, min_value: T, max_value: T) -> Vec<T>
8-
where
9-
T: Copy + rand::distributions::uniform::SampleUniform,
10-
{
11-
let rng = thread_rng();
12-
let uni = Uniform::new_inclusive(min_value, max_value);
13-
rng.sample_iter(uni).take(n).collect()
14-
}
158

169
// worst case array that alternates between increasing max and decreasing min values
1710
pub fn get_worst_case_array<T>(n: usize, step: T) -> Vec<T>
@@ -32,3 +25,60 @@ where
3225
}
3326
arr
3427
}
28+
29+
pub trait SampleUniformFullRange: rand::distributions::uniform::SampleUniform {
30+
const MIN: Self;
31+
const MAX: Self;
32+
33+
// random array that samples between min and max of Self
34+
fn get_random_array(n: usize) -> Vec<Self>
35+
where
36+
Self: Copy + rand::distributions::uniform::SampleUniform,
37+
{
38+
let rng = thread_rng();
39+
let uni = Uniform::new_inclusive(Self::MIN, Self::MAX);
40+
rng.sample_iter(uni).take(n).collect()
41+
}
42+
}
43+
44+
macro_rules! impl_full_range_uniform {
45+
($($t:ty),*) => {
46+
$(
47+
impl SampleUniformFullRange for $t {
48+
const MIN: Self = <$t>::MIN;
49+
const MAX: Self = <$t>::MAX;
50+
}
51+
)*
52+
};
53+
}
54+
55+
macro_rules! impl_full_range_uniform_float {
56+
($($t:ty, $t_int:ty),*) => {
57+
$(
58+
impl SampleUniformFullRange for $t {
59+
// These 2 are not used, but are required by the trait
60+
const MIN: Self = <$t>::MIN;
61+
const MAX: Self = <$t>::MAX;
62+
63+
fn get_random_array(n: usize) -> Vec<Self>
64+
where
65+
Self: Copy + rand::distributions::uniform::SampleUniform,
66+
{
67+
// Get a uniform random array of integers
68+
let rand_arr_int: Vec<$t_int> = <$t_int>::get_random_array(n);
69+
// Transmute the integers to floats
70+
let rand_arr_float: Vec<Self> = unsafe { std::mem::transmute(rand_arr_int) };
71+
// Replace the NaNs with 0.0
72+
rand_arr_float.iter().map(|x| if x.is_nan() { <$t>::zero() } else { *x }).collect()
73+
}
74+
}
75+
)*
76+
};
77+
}
78+
79+
impl_full_range_uniform!(i8, i16, i32, i64, u8, u16, u32, u64);
80+
// f16 does not suffer from range overflow panick as upcast to f32 is used to generate
81+
// the random numbers
82+
impl_full_range_uniform!(f16);
83+
// Workaround for f32 and f64 as these suffer from range overflow in the rand crate
84+
impl_full_range_uniform_float!(f32, i32, f64, i64);

src/scalar/scalar_f16.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,10 +238,8 @@ mod tests {
238238
const ARR_LEN: usize = 1025;
239239

240240
fn get_arrays(len: usize) -> (Vec<f32>, Vec<f16>) {
241-
// we use i8 its to make sure we have correct representation in float
242-
let v = utils::get_random_array(len, i8::MIN, i8::MAX);
243-
let vec_f32: Vec<f32> = v.iter().map(|x| *x as f32).collect();
244-
let vec_f16: Vec<f16> = vec_f32.iter().map(|x| f16::from_f32(*x)).collect();
241+
let vec_f16: Vec<f16> = utils::SampleUniformFullRange::get_random_array(len);
242+
let vec_f32: Vec<f32> = vec_f16.iter().map(|x| x.to_f32()).collect();
245243
(vec_f32, vec_f16)
246244
}
247245

src/simd/simd_f16_ignore_nan.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -726,8 +726,7 @@ mod tests {
726726
use dev_utils::utils;
727727

728728
fn get_array_f16(n: usize) -> Vec<f16> {
729-
let arr = utils::get_random_array(n, i16::MIN, i16::MAX);
730-
arr.iter().map(|x| f16::from_f32(*x as f32)).collect()
729+
utils::SampleUniformFullRange::get_random_array(n)
731730
}
732731

733732
// The scalar implementation

src/simd/simd_f16_return_nan.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -687,8 +687,7 @@ mod tests {
687687
use dev_utils::utils;
688688

689689
fn get_array_f16(n: usize) -> Vec<f16> {
690-
let arr = utils::get_random_array(n, i16::MIN, i16::MAX);
691-
arr.iter().map(|x| f16::from_f32(*x as f32)).collect()
690+
utils::SampleUniformFullRange::get_random_array(n)
692691
}
693692

694693
// The scalar implementation

src/simd/simd_f32_ignore_nan.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ mod tests {
355355
use dev_utils::utils;
356356

357357
fn get_array_f32(n: usize) -> Vec<f32> {
358-
utils::get_random_array(n, f32::MIN, f32::MAX)
358+
utils::SampleUniformFullRange::get_random_array(n)
359359
}
360360

361361
// The scalar implementation

src/simd/simd_f32_return_nan.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ mod tests {
501501
use dev_utils::utils;
502502

503503
fn get_array_f32(n: usize) -> Vec<f32> {
504-
utils::get_random_array(n, f32::MIN, f32::MAX)
504+
utils::SampleUniformFullRange::get_random_array(n)
505505
}
506506

507507
// The scalar implementation

src/simd/simd_f64_ignore_nan.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ mod tests {
377377
use dev_utils::utils;
378378

379379
fn get_array_f64(n: usize) -> Vec<f64> {
380-
utils::get_random_array(n, f64::MIN, f64::MAX)
380+
utils::SampleUniformFullRange::get_random_array(n)
381381
}
382382

383383
// The scalar implementation

src/simd/simd_f64_return_nan.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ mod tests {
552552
use dev_utils::utils;
553553

554554
fn get_array_f64(n: usize) -> Vec<f64> {
555-
utils::get_random_array(n, f64::MIN, f64::MAX)
555+
utils::SampleUniformFullRange::get_random_array(n)
556556
}
557557

558558
// The scalar implementation

src/simd/simd_i16.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ mod tests {
538538
use dev_utils::utils;
539539

540540
fn get_array_i16(n: usize) -> Vec<i16> {
541-
utils::get_random_array(n, i16::MIN, i16::MAX)
541+
utils::SampleUniformFullRange::get_random_array(n)
542542
}
543543

544544
// The scalar implementation

0 commit comments

Comments
 (0)