Skip to content
8 changes: 8 additions & 0 deletions encodings/runend/src/trace_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ fn trace_compare_on_runend() -> VortexResult<()> {
iter 0 current=vortex.runend(bool, len=9) builder_active=false
execute_until target=AnyCanonical root=vortex.binary(bool, len=3)
iter 0 current=vortex.binary(bool, len=3) builder_active=false
optimize root=vortex.slice(i32, len=1) session=false
reduce_parent static:SliceReduceAdaptor(Constant) slot=0 parent=vortex.slice(i32, len=1) child=vortex.constant(i32, len=3) -> vortex.constant(i32, len=1)
done output=vortex.constant(i32, len=1)
execute_until target=AnyCanonical root=vortex.constant(i32, len=1)
iter 0 current=vortex.constant(i32, len=1) builder_active=false
Done array=vortex.primitive(i32, len=1)
iter 1 current=vortex.primitive(i32, len=1) builder_active=false
return output=vortex.primitive(i32, len=1)
Done array=vortex.bool(bool, len=3)
iter 1 current=vortex.bool(bool, len=3) builder_active=false
return output=vortex.bool(bool, len=3)
Expand Down
115 changes: 115 additions & 0 deletions vortex-array/benches/compare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#![expect(clippy::unwrap_used)]

use divan::Bencher;
use divan::counter::ItemsCount;
use mimalloc::MiMalloc;
use rand::RngExt;
use rand::SeedableRng;
Expand Down Expand Up @@ -38,6 +39,7 @@ const ARRAY_SIZE: usize = 65_536;
fn bench_compare(bencher: Bencher, lhs: ArrayRef, rhs: ArrayRef, op: Operator) {
let session = vortex_array::array_session();
bencher
.counter(ItemsCount::new(ARRAY_SIZE))
.with_inputs(|| (&lhs, &rhs, session.create_execution_ctx()))
.bench_refs(|input| {
input
Expand All @@ -49,6 +51,31 @@ fn bench_compare(bencher: Bencher, lhs: ArrayRef, rhs: ArrayRef, op: Operator) {
});
}

fn u8_array(offset: u8) -> ArrayRef {
(0u8..=u8::MAX)
.cycle()
.take(ARRAY_SIZE)
.map(|value| value.wrapping_add(offset))
.collect::<Buffer<_>>()
.into_array()
}

fn i32_array(offset: i32) -> ArrayRef {
(0i32..)
.take(ARRAY_SIZE)
.map(|value| value.wrapping_mul(31).wrapping_add(offset))
.collect::<Buffer<_>>()
.into_array()
}

fn u64_array(offset: u64) -> ArrayRef {
(0u64..)
.take(ARRAY_SIZE)
.map(|value| value.wrapping_mul(31).wrapping_add(offset))
.collect::<Buffer<_>>()
.into_array()
}

fn bool_array(rng: &mut StdRng) -> ArrayRef {
BoolArray::from_iter((0..ARRAY_SIZE).map(|_| rng.random_bool(0.5))).into_array()
}
Expand Down Expand Up @@ -87,6 +114,13 @@ fn float_array(rng: &mut StdRng) -> ArrayRef {
.into_array()
}

fn f32_array(rng: &mut StdRng) -> ArrayRef {
(0..ARRAY_SIZE)
.map(|_| rng.random_range(0.0f32..1.0))
.collect::<Buffer<_>>()
.into_array()
}

fn string_array(rng: &mut StdRng) -> ArrayRef {
VarBinViewArray::from_iter_str((0..ARRAY_SIZE).map(|_| {
let len = rng.random_range(1usize..24);
Expand Down Expand Up @@ -153,6 +187,14 @@ fn compare_int_constant(bencher: Bencher) {
bench_compare(bencher, arr, constant, Operator::Gte);
}

#[divan::bench]
fn compare_int_constant_lhs(bencher: Bencher) {
let mut rng = StdRng::seed_from_u64(0);
let constant = ConstantArray::new(50_000_000i64, ARRAY_SIZE).into_array();
let arr = int_array(&mut rng);
bench_compare(bencher, constant, arr, Operator::Gte);
}

#[divan::bench]
fn compare_int_eq(bencher: Bencher) {
let mut rng = StdRng::seed_from_u64(0);
Expand All @@ -161,6 +203,55 @@ fn compare_int_eq(bencher: Bencher) {
bench_compare(bencher, arr1, arr2, Operator::Eq);
}

#[divan::bench]
fn compare_i32(bencher: Bencher) {
let lhs = i32_array(1);
let rhs = i32_array(17);
bench_compare(bencher, lhs, rhs, Operator::Gte);
}

#[divan::bench]
fn compare_i32_constant(bencher: Bencher) {
let lhs = i32_array(1);
let rhs = ConstantArray::new(1_000_000i32, ARRAY_SIZE).into_array();
bench_compare(bencher, lhs, rhs, Operator::Gte);
}

#[divan::bench]
fn compare_u8(bencher: Bencher) {
let lhs = u8_array(1);
let rhs = u8_array(17);
bench_compare(bencher, lhs, rhs, Operator::Gte);
}

#[divan::bench]
fn compare_u8_constant(bencher: Bencher) {
let lhs = u8_array(1);
let rhs = ConstantArray::new(127u8, ARRAY_SIZE).into_array();
bench_compare(bencher, lhs, rhs, Operator::Gte);
}

#[divan::bench]
fn compare_u64(bencher: Bencher) {
let lhs = u64_array(1);
let rhs = u64_array(17);
bench_compare(bencher, lhs, rhs, Operator::Gte);
}

#[divan::bench]
fn compare_u64_constant(bencher: Bencher) {
let lhs = u64_array(1);
let rhs = ConstantArray::new(1_000_000u64, ARRAY_SIZE).into_array();
bench_compare(bencher, lhs, rhs, Operator::Gte);
}

#[divan::bench]
fn compare_u64_eq(bencher: Bencher) {
let lhs = u64_array(1);
let rhs = u64_array(17);
bench_compare(bencher, lhs, rhs, Operator::Eq);
}

#[divan::bench]
fn compare_float(bencher: Bencher) {
let mut rng = StdRng::seed_from_u64(0);
Expand All @@ -169,6 +260,30 @@ fn compare_float(bencher: Bencher) {
bench_compare(bencher, arr1, arr2, Operator::Gte);
}

#[divan::bench]
fn compare_float_eq(bencher: Bencher) {
let mut rng = StdRng::seed_from_u64(0);
let arr1 = float_array(&mut rng);
let arr2 = float_array(&mut rng);
bench_compare(bencher, arr1, arr2, Operator::Eq);
}

#[divan::bench]
fn compare_f32(bencher: Bencher) {
let mut rng = StdRng::seed_from_u64(0);
let arr1 = f32_array(&mut rng);
let arr2 = f32_array(&mut rng);
bench_compare(bencher, arr1, arr2, Operator::Gte);
}

#[divan::bench]
fn compare_f32_eq(bencher: Bencher) {
let mut rng = StdRng::seed_from_u64(0);
let arr1 = f32_array(&mut rng);
let arr2 = f32_array(&mut rng);
bench_compare(bencher, arr1, arr2, Operator::Eq);
}

#[divan::bench]
fn compare_decimal(bencher: Bencher) {
let mut rng = StdRng::seed_from_u64(0);
Expand Down
8 changes: 4 additions & 4 deletions vortex-array/src/scalar_fn/fns/binary/compare/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
//! Native comparison kernels.
//!
//! [`execute_compare`] dispatches on the logical [`DType`] of its operands and evaluates every
//! comparison directly over Vortex canonical arraysbit buffers for booleans, lane kernels from
//! `vortex-compute` for primitives and decimals, binary views for strings/bytes, and a row-wise
//! comparator for nested types. There is no Arrow fallback.
//! comparison directly over Vortex canonical arrays: bit buffers for booleans, row or fused lane
//! kernels for primitives, lane kernels for decimals, binary views for strings and bytes, and a
//! row-wise comparator for nested types. There is no Arrow fallback.
//!
//! Floating point values compare with Vortex's total ordering (`NaN` is the largest value,
//! `-0.0 < +0.0`, and equality is bitwise), matching [`Scalar`] comparison semantics.
Expand Down Expand Up @@ -211,7 +211,7 @@ fn compare_arrays(
)
.into_array()),
DType::Bool(_) => boolean::compare_bool(lhs, rhs, op, nullability, ctx),
DType::Primitive(..) => primitive::compare_primitive(lhs, rhs, op, nullability, ctx),
DType::Primitive(..) => primitive::compare_primitive(lhs, rhs, op, ctx),
DType::Decimal(..) => decimal::compare_decimal(lhs, rhs, op, nullability, ctx),
DType::Utf8(_) | DType::Binary(_) => bytes::compare_bytes(lhs, rhs, op, nullability, ctx),
DType::Struct(..) | DType::List(..) | DType::FixedSizeList(..) | DType::Map(..) => {
Expand Down
Loading
Loading