Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔍 add searchsorted to get equidistant x-bins #11

Merged
merged 30 commits into from Dec 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c030eb5
:broom: rename np.bool8 -> np.bool_
jvdd Dec 22, 2022
82463de
:construction: add searchsorted functionality
jvdd Dec 22, 2022
0473a20
:hiking_boot: cleanup implementation
jvdd Dec 22, 2022
27a9279
:recycle: change m4 implementation
jvdd Dec 23, 2022
c34c4ad
:broom:
jvdd Dec 23, 2022
be032fb
:recycle: refactoring + updated MinMax algorithm
jvdd Dec 23, 2022
a906aea
:construction:
jvdd Dec 23, 2022
58e92ba
:recycle: use f64 for val_step calculation
jvdd Dec 23, 2022
964f22d
:bug:
jvdd Dec 23, 2022
6603548
:fire: make it fast again
jvdd Dec 23, 2022
b7cb4cd
:broom:
jvdd Dec 23, 2022
12fadae
:fire: update minmaxlttb algorithm
jvdd Dec 23, 2022
ad388bc
:crab: update bindings
jvdd Dec 23, 2022
68d6618
:innocent: do not support f16 as x datatype
jvdd Dec 24, 2022
6f8238f
:broom: use num_traits
jvdd Dec 24, 2022
1e6c44a
:broom:
jvdd Dec 24, 2022
6a08fce
:santa: finish python bindings
jvdd Dec 24, 2022
c493815
:art: update readme
jvdd Dec 24, 2022
3428999
:santa: add timedelta64 to readme
jvdd Dec 24, 2022
69f06e0
:broom: consistent naming
jvdd Dec 24, 2022
d182e0c
:santa: check n_out requirements
jvdd Dec 24, 2022
b762e68
:construction:
jvdd Dec 27, 2022
92d03d3
:fire: fix out of bounds indexing issue
jvdd Dec 28, 2022
6688e11
:broom: use f64 to calculate equidistant step
jvdd Dec 28, 2022
ad60f75
:fire: check against plotly-resampler downsamplers
jvdd Dec 29, 2022
1e147c8
:broom: cleanup
jvdd Dec 29, 2022
c59434a
:pray: new release
jvdd Dec 29, 2022
153199a
:see_no_evil:
jvdd Dec 29, 2022
0530b30
:broom:
jvdd Dec 29, 2022
d3592ee
:broom:
jvdd Dec 29, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/ci-downsample_rs.yml
Expand Up @@ -42,7 +42,6 @@ jobs:
run: cargo check --verbose --all-features
- name: formatting check
run: cargo fmt --all -- --check
# TODO: enable clippy once I write docs for all public items
# - name: check with clippy
# run: cargo clippy --all --all-targets --all-features -- -D warnings

Expand Down
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -28,8 +28,8 @@
- no intermediate data structures are created
* **Flexible**: works on any type of data
- supported datatypes are
- for `x`: `f16`, `f32`, `f64`, `i16`, `i32`, `i64`, `u16`, `u32`, `u64`, `datetime64`
- for `y`: `f16`, `f32`, `f64`, `i8`, `i16`, `i32`, `i64`, `u8`, `u16`, `u32`, `u64`, `bool`
- for `x`: `f32`, `f64`, `i16`, `i32`, `i64`, `u16`, `u32`, `u64`, `datetime64`, `timedelta64`
- for `y`: `f16`, `f32`, `f64`, `i8`, `i16`, `i32`, `i64`, `u8`, `u16`, `u32`, `u64`, `datetime64`, `timedelta64`, `bool`
<details>
<summary><i>!! 🚀 <code>f16</code> <a href="https://github.com/jvdd/argminmax">argminmax</a> is 200-300x faster than numpy</i></summary>
In contrast with all other data types above, <code>f16</code> is *not* hardware supported (i.e., no instructions for f16) by most modern CPUs!! <br>
Expand Down
5 changes: 4 additions & 1 deletion downsample_rs/Cargo.toml
Expand Up @@ -7,9 +7,12 @@ description = "Downsample time series data"
license = "MIT"

[dependencies]
# TODO: perhaps use polars?
ndarray = {version = "0.15.6", default-features = false, features = ["rayon"] }
argminmax = { version = "0.3" , features = ["half"] }
half = { version = "2.1", default-features = false , optional = true}
half = { version = "2.1", default-features = false , features=["num-traits"], optional = true}
num-traits = { version = "0.2.15", default-features = false }
rayon = { version = "1.6.0", default-features = false }

[dev-dependencies]
criterion = "0.3.0"
Expand Down
12 changes: 6 additions & 6 deletions downsample_rs/benches/bench_lttb.rs
Expand Up @@ -12,30 +12,30 @@ fn lttb_f32_random_array_long(c: &mut Criterion) {
let n = config::ARRAY_LENGTH_LONG;
let x = Array1::from((0..n).map(|i| i as i32).collect::<Vec<i32>>());
let y = utils::get_random_array::<f32>(n, f32::MIN, f32::MAX);
c.bench_function("lttb_scal_f32", |b| {
b.iter(|| lttb_mod::lttb(black_box(x.view()), black_box(y.view()), black_box(2_000)))
c.bench_function("lttb_scalx_f32", |b| {
b.iter(|| lttb_mod::lttb_with_x(black_box(x.view()), black_box(y.view()), black_box(2_000)))
});
}
fn lttb_f32_random_array_50m(c: &mut Criterion) {
let n = 50_000_000;
let x = Array1::from((0..n).map(|i| i as i32).collect::<Vec<i32>>());
let y = utils::get_random_array::<f32>(n, f32::MIN, f32::MAX);
c.bench_function("lttb_scal_50M_f32", |b| {
b.iter(|| lttb_mod::lttb(black_box(x.view()), black_box(y.view()), black_box(2_000)))
c.bench_function("lttb_scalx_50M_f32", |b| {
b.iter(|| lttb_mod::lttb_with_x(black_box(x.view()), black_box(y.view()), black_box(2_000)))
});
}

fn lttb_without_x_f32_random_array_long(c: &mut Criterion) {
let n = config::ARRAY_LENGTH_LONG;
let y = utils::get_random_array::<f32>(n, f32::MIN, f32::MAX);
c.bench_function("lttbnox_scal_f32", |b| {
c.bench_function("lttb_scal_f32", |b| {
b.iter(|| lttb_mod::lttb_without_x(black_box(y.view()), black_box(2_000)))
});
}
fn lttb_without_x_f32_random_array_50m(c: &mut Criterion) {
let n = 50_000_000;
let y = utils::get_random_array::<f32>(n, f32::MIN, f32::MAX);
c.bench_function("lttbnox_scal_50M_f32", |b| {
c.bench_function("lttb_scal_50M_f32", |b| {
b.iter(|| lttb_mod::lttb_without_x(black_box(y.view()), black_box(2_000)))
});
}
Expand Down
56 changes: 48 additions & 8 deletions downsample_rs/benches/bench_m4.rs
Expand Up @@ -7,47 +7,87 @@ use downsample_rs::m4 as m4_mod;
use criterion::{black_box, Criterion};
use dev_utils::{config, utils};

use ndarray::Array1;

fn m4_f32_random_array_long_single_core(c: &mut Criterion) {
let n = config::ARRAY_LENGTH_LONG;
let data = utils::get_random_array::<f32>(n, f32::MIN, f32::MAX);
c.bench_function("m4_scal_f32", |b| {
b.iter(|| m4_mod::m4_scalar(black_box(data.view()), black_box(2_000)))
b.iter(|| m4_mod::m4_scalar_without_x(black_box(data.view()), black_box(2_000)))
});
c.bench_function("m4_simd_f32", |b| {
b.iter(|| m4_mod::m4_simd(black_box(data.view()), black_box(2_000)))
b.iter(|| m4_mod::m4_simd_without_x(black_box(data.view()), black_box(2_000)))
});
}

fn m4_f32_random_array_long_multi_core(c: &mut Criterion) {
let n = config::ARRAY_LENGTH_LONG;
let data = utils::get_random_array::<f32>(n, f32::MIN, f32::MAX);
c.bench_function("m4_scal_p_f32", |b| {
b.iter(|| m4_mod::m4_scalar_parallel(black_box(data.view()), black_box(2_000)))
b.iter(|| m4_mod::m4_scalar_without_x_parallel(black_box(data.view()), black_box(2_000)))
});
c.bench_function("m4_simd_p_f32", |b| {
b.iter(|| m4_mod::m4_simd_parallel(black_box(data.view()), black_box(2_000)))
b.iter(|| m4_mod::m4_simd_without_x_parallel(black_box(data.view()), black_box(2_000)))
});
}

fn m4_f32_random_array_50M_single_core(c: &mut Criterion) {
let n = 50_000_000;
let data = utils::get_random_array::<f32>(n, f32::MIN, f32::MAX);
let x = Array1::from((0..n).map(|i| i as i32).collect::<Vec<i32>>());
c.bench_function("m4_scal_50M_f32", |b| {
b.iter(|| m4_mod::m4_scalar(black_box(data.view()), black_box(2_000)))
b.iter(|| m4_mod::m4_scalar_without_x(black_box(data.view()), black_box(2_000)))
});
c.bench_function("m4_simd_50M_f32", |b| {
b.iter(|| m4_mod::m4_simd(black_box(data.view()), black_box(2_000)))
b.iter(|| m4_mod::m4_simd_without_x(black_box(data.view()), black_box(2_000)))
});
c.bench_function("m4_scalx_50M_f32", |b| {
b.iter(|| {
m4_mod::m4_scalar_with_x(
black_box(x.view()),
black_box(data.view()),
black_box(2_000),
)
})
});
c.bench_function("m4_simdx_50M_f32", |b| {
b.iter(|| {
m4_mod::m4_simd_with_x(
black_box(x.view()),
black_box(data.view()),
black_box(2_000),
)
})
});
}

fn m4_f32_random_array_50M_multi_core(c: &mut Criterion) {
let n = 50_000_000;
let data = utils::get_random_array::<f32>(n, f32::MIN, f32::MAX);
let x = Array1::from((0..n).map(|i| i as i32).collect::<Vec<i32>>());
c.bench_function("m4_scal_p_50M_f32", |b| {
b.iter(|| m4_mod::m4_scalar_parallel(black_box(data.view()), black_box(2_000)))
b.iter(|| m4_mod::m4_scalar_without_x_parallel(black_box(data.view()), black_box(2_000)))
});
c.bench_function("m4_simd_p_50M_f32", |b| {
b.iter(|| m4_mod::m4_simd_parallel(black_box(data.view()), black_box(2_000)))
b.iter(|| m4_mod::m4_simd_without_x_parallel(black_box(data.view()), black_box(2_000)))
});
c.bench_function("m4_scalx_p_50M_f32", |b| {
b.iter(|| {
m4_mod::m4_scalar_with_x_parallel(
black_box(x.view()),
black_box(data.view()),
black_box(2_000),
)
})
});
c.bench_function("m4_simdx_p_50M_f32", |b| {
b.iter(|| {
m4_mod::m4_simd_with_x_parallel(
black_box(x.view()),
black_box(data.view()),
black_box(2_000),
)
})
});
}

Expand Down
90 changes: 82 additions & 8 deletions downsample_rs/benches/bench_minmax.rs
Expand Up @@ -7,48 +7,122 @@ use downsample_rs::minmax as minmax_mod;
use criterion::{black_box, Criterion};
use dev_utils::{config, utils};

use ndarray::Array1;

fn minmax_f32_random_array_long_single_core(c: &mut Criterion) {
let n = config::ARRAY_LENGTH_LONG;
let data = utils::get_random_array::<f32>(n, f32::MIN, f32::MAX);
c.bench_function("minmax_scal_f32", |b| {
b.iter(|| minmax_mod::min_max_scalar(black_box(data.view()), black_box(2_000)))
b.iter(|| minmax_mod::min_max_scalar_without_x(black_box(data.view()), black_box(2_000)))
});
c.bench_function("minmax_simd_f32", |b| {
b.iter(|| minmax_mod::min_max_simd(black_box(data.view()), black_box(2_000)))
b.iter(|| minmax_mod::min_max_simd_without_x(black_box(data.view()), black_box(2_000)))
});
}

fn minmax_f32_random_array_long_multi_core(c: &mut Criterion) {
let n = config::ARRAY_LENGTH_LONG;
let data = utils::get_random_array::<f32>(n, f32::MIN, f32::MAX);
c.bench_function("minmax_scal_p_f32", |b| {
b.iter(|| minmax_mod::min_max_scalar_parallel(black_box(data.view()), black_box(2_000)))
b.iter(|| {
minmax_mod::min_max_scalar_without_x_parallel(black_box(data.view()), black_box(2_000))
})
});
c.bench_function("minmax_simd_p_f32", |b| {
b.iter(|| minmax_mod::min_max_simd_parallel(black_box(data.view()), black_box(2_000)))
b.iter(|| {
minmax_mod::min_max_simd_without_x_parallel(black_box(data.view()), black_box(2_000))
})
});
}

fn minmax_f32_random_array_50M_single_core(c: &mut Criterion) {
let n = 50_000_000;
let data = utils::get_random_array::<f32>(n, f32::MIN, f32::MAX);
let x = Array1::from((0..n).map(|i| i as i32).collect::<Vec<i32>>());
c.bench_function("minmax_scal_50M_f32", |b| {
b.iter(|| minmax_mod::min_max_scalar(black_box(data.view()), black_box(2_000)))
b.iter(|| minmax_mod::min_max_scalar_without_x(black_box(data.view()), black_box(2_000)))
});
c.bench_function("minmax_simd_50M_f32", |b| {
b.iter(|| minmax_mod::min_max_simd(black_box(data.view()), black_box(2_000)))
b.iter(|| minmax_mod::min_max_simd_without_x(black_box(data.view()), black_box(2_000)))
});
c.bench_function("minmax_scalx_50M_f32", |b| {
b.iter(|| {
minmax_mod::min_max_scalar_with_x(
black_box(x.view()),
black_box(data.view()),
black_box(2_000),
)
})
});
c.bench_function("minmax_simdx_50M_f32", |b| {
b.iter(|| {
minmax_mod::min_max_simd_with_x(
black_box(x.view()),
black_box(data.view()),
black_box(2_000),
)
})
});

// c.bench_function("minmax_scal_50M_f32", |b| {
// b.iter(|| minmax_mod::min_max_scalar_without_x(black_box(data.view()), black_box(60_000)))
// });
// c.bench_function("minmax_simd_50M_f32", |b| {
// b.iter(|| minmax_mod::min_max_simd_without_x(black_box(data.view()), black_box(60_000)))
// });
// c.bench_function("minmax_scalx_50M_f32", |b| {
// b.iter(|| minmax_mod::min_max_scalar_with_x(black_box(x.view()), black_box(data.view()), black_box(60_000)))
// });
// c.bench_function("minmax_simdx_50M_f32", |b| {
// b.iter(|| minmax_mod::min_max_simd_with_x(black_box(x.view()), black_box(data.view()), black_box(60_000)))
// });
}

fn minmax_f32_random_array_50M_long_multi_core(c: &mut Criterion) {
let n = 50_000_000;
let data = utils::get_random_array::<f32>(n, f32::MIN, f32::MAX);
let x = Array1::from((0..n).map(|i| i as i32).collect::<Vec<i32>>());
c.bench_function("minmax_scal_p_50M_f32", |b| {
b.iter(|| minmax_mod::min_max_scalar_parallel(black_box(data.view()), black_box(2_000)))
b.iter(|| {
minmax_mod::min_max_scalar_without_x_parallel(black_box(data.view()), black_box(2_000))
})
});
c.bench_function("minmax_simd_p_50M_f32", |b| {
b.iter(|| minmax_mod::min_max_simd_parallel(black_box(data.view()), black_box(2_000)))
b.iter(|| {
minmax_mod::min_max_simd_without_x_parallel(black_box(data.view()), black_box(2_000))
})
});
c.bench_function("minmax_scalx_p_50M_f32", |b| {
b.iter(|| {
minmax_mod::min_max_scalar_with_x_parallel(
black_box(x.view()),
black_box(data.view()),
black_box(2_000),
)
})
});
c.bench_function("minmax_simdx_p_50M_f32", |b| {
b.iter(|| {
minmax_mod::min_max_simd_with_x_parallel(
black_box(x.view()),
black_box(data.view()),
black_box(2_000),
)
})
});

// c.bench_function("minmax_scal_p_50M_f32", |b| {
// b.iter(|| minmax_mod::min_max_scalar_without_x_parallel(black_box(data.view()), black_box(60_000)))
// });
// c.bench_function("minmax_simd_p_50M_f32", |b| {
// b.iter(|| minmax_mod::min_max_simd_without_x_parallel(black_box(data.view()), black_box(60_000)))
// });
// c.bench_function("minmax_scalx_p_50M_f32", |b| {
// b.iter(|| minmax_mod::min_max_scalar_with_x_parallel(black_box(x.view()), black_box(data.view()), black_box(60_000)))
// });
// c.bench_function("minmax_simdx_p_50M_f32", |b| {
// b.iter(|| minmax_mod::min_max_simd_with_x_parallel(black_box(x.view()), black_box(data.view()), black_box(60_000)))
// });
}

// fn minmax_f32_worst_case_array_long(c: &mut Criterion) {
Expand Down