Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 16 additions & 47 deletions vortex-array/benches/binary_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,19 @@ const I16_LEN: usize = primitive_len::<i16>();
const I32_LEN: usize = primitive_len::<i32>();
const I64_LEN: usize = primitive_len::<i64>();

/// Per-row against per-row, short and long. This is the shape the operators are tuned for, so it
/// is the one every operator is measured on.
const BINARY_SHAPE_CASES: &[(usize, BinaryShape)] = &[
(128, BinaryShape::PerRowPerRow),
(128, BinaryShape::PerRowConstant),
(128, BinaryShape::ConstantPerRow),
(128, BinaryShape::PerRowNullableConstant),
(I64_LEN, BinaryShape::PerRowPerRow),
];

/// Constant operands are measured on `Add` alone, at the long length.
///
/// Decoding a constant operand, orienting it, and carrying its validity are shared by every
/// operator, so repeating all three shapes under `Sub` and `Mul` costs three walltime legs apiece
/// and measures the same code again. These cases stay as the regression guard on that path.
const CONSTANT_SHAPE_CASES: &[(usize, BinaryShape)] = &[
(I64_LEN, BinaryShape::PerRowConstant),
(I64_LEN, BinaryShape::ConstantPerRow),
(I64_LEN, BinaryShape::PerRowNullableConstant),
Expand All @@ -90,6 +97,12 @@ fn add_shapes(bencher: Bencher, &(len, shape): &(usize, BinaryShape)) {
bench_binary_shape(bencher, len, shape, Operator::Add);
}

#[vortex_bench_support::cpu_features]
#[divan::bench(args = CONSTANT_SHAPE_CASES)]
fn add_constant_shapes(bencher: Bencher, &(len, shape): &(usize, BinaryShape)) {
bench_binary_shape(bencher, len, shape, Operator::Add);
}

#[vortex_bench_support::cpu_features]
#[divan::bench(args = BINARY_SHAPE_CASES)]
fn subtract_shapes(bencher: Bencher, &(len, shape): &(usize, BinaryShape)) {
Expand Down Expand Up @@ -136,15 +149,6 @@ fn add_i64_nullable(bencher: Bencher) {
bench_primitive(bencher, lhs, rhs, Operator::Add);
}

#[vortex_bench_support::cpu_features]
#[divan::bench]
fn add_i64_constant(bencher: Bencher) {
let lhs = primitive_nonnull(0, I64_LEN).into_array();
let rhs = ConstantArray::new(1_000_000i64, I64_LEN).into_array();

bench_primitive(bencher, lhs, rhs, Operator::Add);
}

#[vortex_bench_support::cpu_features]
#[divan::bench]
fn add_i32_nonnull(bencher: Bencher) {
Expand Down Expand Up @@ -244,15 +248,6 @@ fn mul_i32_nullable(bencher: Bencher) {
bench_primitive(bencher, lhs, rhs, Operator::Mul);
}

#[vortex_bench_support::cpu_features]
#[divan::bench]
fn mul_i32_constant(bencher: Bencher) {
let lhs = primitive_i32_small_nonnull(1, I32_LEN).into_array();
let rhs = ConstantArray::new(31i32, I32_LEN).into_array();

bench_primitive(bencher, lhs, rhs, Operator::Mul);
}

#[vortex_bench_support::cpu_features]
#[divan::bench]
fn div_i64_nonnull(bencher: Bencher) {
Expand All @@ -271,15 +266,6 @@ fn div_i64_nullable(bencher: Bencher) {
bench_primitive(bencher, lhs, rhs, Operator::Div);
}

#[vortex_bench_support::cpu_features]
#[divan::bench]
fn sub_i64_constant(bencher: Bencher) {
let lhs = primitive_nonnull(0, I64_LEN).into_array();
let rhs = ConstantArray::new(37i64, I64_LEN).into_array();

bench_primitive(bencher, lhs, rhs, Operator::Sub);
}

#[divan::bench]
fn add_decimal_i64_nonnull(bencher: Bencher) {
let lhs = decimal_i64_nonnull(0, LEN).into_array();
Expand Down Expand Up @@ -328,15 +314,6 @@ fn div_decimal_i128_nullable(bencher: Bencher) {
bench_decimal(bencher, lhs, rhs, Operator::Div);
}

#[vortex_bench_support::cpu_features]
#[divan::bench]
fn eq_i64_constant(bencher: Bencher) {
let lhs = primitive_nonnull(0, LEN).into_array();
let rhs = ConstantArray::new(1024i64, LEN).into_array();

bench_bool(bencher, lhs, rhs, Operator::Eq);
}

#[vortex_bench_support::cpu_features]
#[divan::bench]
fn lt_i64_nullable(bencher: Bencher) {
Expand All @@ -354,14 +331,6 @@ fn and_bool_nullable(bencher: Bencher) {
bench_bool(bencher, lhs, rhs, Operator::And);
}

#[divan::bench]
fn or_bool_constant(bencher: Bencher) {
let lhs = bool_nullable(2, 7).into_array();
let rhs = ConstantArray::new(true, LEN).into_array();

bench_bool(bencher, lhs, rhs, Operator::Or);
}

fn bench_primitive(bencher: Bencher, lhs: ArrayRef, rhs: ArrayRef, operator: Operator) {
bench_binary::<PrimitiveArray>(bencher, lhs, rhs, operator);
}
Expand Down
14 changes: 5 additions & 9 deletions vortex-array/benches/compare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
//! selected through `cfg(target_feature)` has to beat, measured on the silicon it would run
//! on.
//!
//! Every case here compares one array against another, which is the shape the path is tuned for.
//! The three constant cases that remain — boolean, integer, and string — are a regression guard on
//! constant handling rather than coverage of it: a constant operand is decoded the same way
//! whatever it holds. Constant orientation is measured once, in `binary_ops.rs`.
//!
//! The boolean, decimal, string, and struct cases are not tagged. A wider vector register is
//! not what decides them: booleans are already word-at-a-time over a bitmap, decimals are
//! `i128`, and the string and struct cases are dominated by view chasing and per-field
Expand Down Expand Up @@ -196,15 +201,6 @@ fn compare_int_constant(bencher: Bencher) {
bench_compare(bencher, arr, constant, Operator::Gte);
}

#[vortex_bench_support::cpu_features]
#[divan::bench]
fn compare_int_constant_left(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::Lte);
}

#[vortex_bench_support::cpu_features]
#[divan::bench]
fn compare_u8(bencher: Bencher) {
Expand Down
30 changes: 25 additions & 5 deletions vortex-array/benches/row_fn_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,17 @@ static SESSION: LazyLock<VortexSession> = LazyLock::new(array_session);

const ROWS: usize = 1 << 14;

const INPUT_SHAPES: &[InputShape] = &[
InputShape::PerRowPerRow,
InputShape::PerRowConstant,
InputShape::ConstantPerRow,
];
/// The shape every row function is measured on: one per-row operand against another.
const INPUT_SHAPES: &[InputShape] = &[InputShape::PerRowPerRow];

/// Constant operands are measured on `i64` alone, by the `*_constant` benchmarks below.
///
/// The row executor decodes and orients a constant operand the same way whatever the row kernel
/// does with the value, so running both constant orientations under every element type and every
/// output mode measures one path repeatedly, three walltime legs at a time. One infallible pair and
/// one deferred pair keep it covered: those two differ in how a constant row reaches the kernel,
/// and that is the difference worth watching.
const CONSTANT_SHAPES: &[InputShape] = &[InputShape::PerRowConstant, InputShape::ConstantPerRow];

#[derive(Clone, Copy, Debug)]
enum InputShape {
Expand Down Expand Up @@ -182,13 +188,27 @@ fn infallible_bool<T: BenchPrimitive>(bencher: Bencher, &shape: &InputShape) {
bench_row_fn(bencher, &function, make_args::<T>(shape));
}

#[vortex_bench_support::cpu_features]
#[divan::bench(args = CONSTANT_SHAPES)]
fn infallible_bool_constant(bencher: Bencher, &shape: &InputShape) {
let function = InfallibleBool::<i64>(PhantomData);
bench_row_fn(bencher, &function, make_args::<i64>(shape));
}

#[vortex_bench_support::cpu_features]
#[divan::bench(types = [i32, i64], args = INPUT_SHAPES)]
fn deferred_bool<T: BenchPrimitive>(bencher: Bencher, &shape: &InputShape) {
let function = DeferredBool::<T>(PhantomData);
bench_row_fn(bencher, &function, make_args::<T>(shape));
}

#[vortex_bench_support::cpu_features]
#[divan::bench(args = CONSTANT_SHAPES)]
fn deferred_bool_constant(bencher: Bencher, &shape: &InputShape) {
let function = DeferredBool::<i64>(PhantomData);
bench_row_fn(bencher, &function, make_args::<i64>(shape));
}

#[vortex_bench_support::cpu_features]
#[divan::bench(args = INPUT_SHAPES)]
fn deferred_i64(bencher: Bencher, &shape: &InputShape) {
Expand Down
Loading