Skip to content

Commit 8031285

Browse files
Merge branch 'develop' into ji/slots-for-arrays
2 parents 77d14a4 + 8e1fe29 commit 8031285

4 files changed

Lines changed: 139 additions & 16 deletions

File tree

.github/workflows/ci.yml

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -494,9 +494,22 @@ jobs:
494494
495495
cuda-test-sanitizer:
496496
if: github.repository == 'vortex-data/vortex'
497-
name: "CUDA tests (sanitizer)"
497+
name: "CUDA tests (${{ matrix.sanitizer }})"
498498
timeout-minutes: 30
499499
runs-on: runs-on=${{ github.run_id }}/runner=gpu/tag=cuda-test-sanitizer
500+
strategy:
501+
fail-fast: false
502+
matrix:
503+
include:
504+
- sanitizer: memcheck
505+
runner_flags: "--tool memcheck --leak-check=full --error-exitcode 1"
506+
# TODO(joe): try to re-enable racecheck, it is hanging in CI.
507+
# - sanitizer: racecheck
508+
# runner_flags: "--tool racecheck --error-exitcode 1"
509+
- sanitizer: synccheck
510+
runner_flags: "--tool synccheck --error-exitcode 1"
511+
- sanitizer: initcheck
512+
runner_flags: "--tool initcheck --error-exitcode 1"
500513
steps:
501514
- uses: runs-on/action@v2
502515
with:
@@ -510,22 +523,11 @@ jobs:
510523
- uses: ./.github/actions/setup-rust
511524
with:
512525
repo-token: ${{ secrets.GITHUB_TOKEN }}
513-
- name: CUDA - memcheck
514-
env:
515-
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: compute-sanitizer --tool memcheck --leak-check=full --error-exitcode 1
516-
run: cargo test --locked -p vortex-cuda --all-features --target x86_64-unknown-linux-gnu
517-
# TODO(joe): try to re-enable, This is hanging in CI.
518-
# - name: CUDA - racecheck
519-
# env:
520-
# CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: compute-sanitizer --tool racecheck --error-exitcode 1
521-
# run: cargo test --locked -p vortex-cuda --all-features --target x86_64-unknown-linux-gnu
522-
- name: CUDA - synccheck
523-
env:
524-
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: compute-sanitizer --tool synccheck --error-exitcode 1
525-
run: cargo test --locked -p vortex-cuda --all-features --target x86_64-unknown-linux-gnu
526-
- name: CUDA - initcheck
526+
- name: Build tests
527+
run: cargo test --locked -p vortex-cuda --all-features --target x86_64-unknown-linux-gnu --no-run
528+
- name: "CUDA - ${{ matrix.sanitizer }}"
527529
env:
528-
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: compute-sanitizer --tool initcheck --error-exitcode 1
530+
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: "compute-sanitizer ${{ matrix.runner_flags }}"
529531
run: cargo test --locked -p vortex-cuda --all-features --target x86_64-unknown-linux-gnu
530532

531533
cuda-test-cudf:

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vortex-mask/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@ vortex-buffer = { workspace = true, features = ["arrow"] }
2828
vortex-error = { workspace = true }
2929

3030
[dev-dependencies]
31+
divan = { workspace = true }
3132
rstest = { workspace = true }
3233

34+
[[bench]]
35+
name = "intersect_by_rank"
36+
harness = false
37+
3338
[lints]
3439
workspace = true
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
//! Benchmarks for `intersect_by_rank`.
5+
6+
#![allow(clippy::unwrap_used, clippy::cast_possible_truncation)]
7+
8+
use divan::Bencher;
9+
use vortex_buffer::BitBuffer;
10+
use vortex_mask::Mask;
11+
12+
fn main() {
13+
divan::main();
14+
}
15+
16+
// Standard test cases
17+
const BENCH_ARGS: &[(usize, &str)] = &[
18+
(10_000, "random"),
19+
(10_000, "runs"),
20+
(100_000, "random"),
21+
(100_000, "runs"),
22+
];
23+
24+
// Sparse test cases (varying base selectivity)
25+
const SPARSE_ARGS: &[(usize, f64, &str)] = &[
26+
(100_000, 0.01, "sparse_1pct"),
27+
(100_000, 0.05, "sparse_5pct"),
28+
(100_000, 0.10, "sparse_10pct"),
29+
(100_000, 0.50, "dense_50pct"),
30+
];
31+
32+
// Four-case density matrix: (self_density, mask_density)
33+
const DENSITY_MATRIX_ARGS: &[(f64, f64, &str)] = &[
34+
(0.05, 0.05, "self_sparse_mask_sparse"),
35+
(0.05, 0.50, "self_sparse_mask_dense"),
36+
(0.50, 0.05, "self_dense_mask_sparse"),
37+
(0.50, 0.50, "self_dense_mask_dense"),
38+
];
39+
40+
fn create_random_mask(len: usize, selectivity: f64) -> Mask {
41+
Mask::from_buffer(BitBuffer::from_iter((0..len).map(|i| {
42+
let threshold = (selectivity * 1000.0) as usize;
43+
(i * 7 + 13) % 1000 < threshold
44+
})))
45+
}
46+
47+
fn create_runs_mask(len: usize, run_len: usize, gap_len: usize) -> Mask {
48+
Mask::from_buffer(BitBuffer::from_iter((0..len).map(|i| {
49+
let cycle = run_len + gap_len;
50+
(i % cycle) < run_len
51+
})))
52+
}
53+
54+
fn create_fixture(size: usize, pattern: &str) -> (Mask, Mask) {
55+
match pattern {
56+
"random" => {
57+
let base = create_random_mask(size, 0.5);
58+
let rank_len = base.true_count();
59+
let rank = create_random_mask(rank_len, 0.5);
60+
(base, rank)
61+
}
62+
"runs" => {
63+
let base = create_runs_mask(size, 64, 64);
64+
let rank_len = base.true_count();
65+
let rank = create_runs_mask(rank_len, 64, 64);
66+
(base, rank)
67+
}
68+
_ => unreachable!(),
69+
}
70+
}
71+
72+
fn create_sparse_fixture(size: usize, selectivity: f64) -> (Mask, Mask) {
73+
let base = create_random_mask(size, selectivity);
74+
let rank_len = base.true_count();
75+
let rank = create_random_mask(rank_len, 0.5);
76+
(base, rank)
77+
}
78+
79+
fn create_density_matrix_fixture(
80+
size: usize,
81+
self_density: f64,
82+
mask_density: f64,
83+
) -> (Mask, Mask) {
84+
let base = create_random_mask(size, self_density);
85+
let rank_len = base.true_count();
86+
let rank = create_random_mask(rank_len, mask_density);
87+
(base, rank)
88+
}
89+
90+
/// Standard patterns (random / runs)
91+
#[divan::bench(args = BENCH_ARGS)]
92+
fn intersect_by_rank(bencher: Bencher, (size, pattern): (usize, &str)) {
93+
let (base, rank) = create_fixture(size, pattern);
94+
bencher
95+
.with_inputs(|| (&base, &rank))
96+
.bench_refs(|(base, rank)| base.intersect_by_rank(rank));
97+
}
98+
99+
/// Sparse base masks (varying selectivity)
100+
#[divan::bench(args = SPARSE_ARGS)]
101+
fn sparse(bencher: Bencher, (size, selectivity, _name): (usize, f64, &str)) {
102+
let (base, rank) = create_sparse_fixture(size, selectivity);
103+
bencher
104+
.with_inputs(|| (&base, &rank))
105+
.bench_refs(|(base, rank)| base.intersect_by_rank(rank));
106+
}
107+
108+
/// Density matrix (self_density x mask_density)
109+
#[divan::bench(args = DENSITY_MATRIX_ARGS)]
110+
fn density_matrix(bencher: Bencher, (self_density, mask_density, _name): (f64, f64, &str)) {
111+
let (base, rank) = create_density_matrix_fixture(100_000, self_density, mask_density);
112+
bencher
113+
.with_inputs(|| (&base, &rank))
114+
.bench_refs(|(base, rank)| base.intersect_by_rank(rank));
115+
}

0 commit comments

Comments
 (0)