Skip to content

Commit a9b93a4

Browse files
Merge branch 'develop' into vortex-geo-pr
2 parents 242ee4c + 9814173 commit a9b93a4

213 files changed

Lines changed: 5644 additions & 2593 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/bench-pr.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,18 @@ jobs:
7272
profiling_frequency: 199
7373
extra_args: "--off-cpu-threshold=0.03" # Personally tuned by @brancz
7474

75+
- name: Run ${{ matrix.benchmark.name }} benchmark (per-combination)
76+
if: matrix.benchmark.id == 'random-access-bench'
77+
shell: bash
78+
env:
79+
RUST_BACKTRACE: full
80+
VORTEX_EXPERIMENTAL_PATCHED_ARRAY: "1"
81+
FLAT_LAYOUT_INLINE_ARRAY_NODE: "1"
82+
run: |
83+
python3 scripts/random-access-split.py
84+
7585
- name: Run ${{ matrix.benchmark.name }} benchmark
86+
if: matrix.benchmark.id != 'random-access-bench'
7687
shell: bash
7788
env:
7889
RUST_BACKTRACE: full

.github/workflows/bench.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,18 @@ jobs:
8585
profiling_frequency: 199
8686
extra_args: "--off-cpu-threshold=0.03" # Personally tuned by @brancz
8787

88+
- name: Run ${{ matrix.benchmark.name }} benchmark (per-combination)
89+
if: matrix.benchmark.id == 'random-access-bench'
90+
shell: bash
91+
env:
92+
RUST_BACKTRACE: full
93+
VORTEX_EXPERIMENTAL_PATCHED_ARRAY: "1"
94+
FLAT_LAYOUT_INLINE_ARRAY_NODE: "1"
95+
run: |
96+
python3 scripts/random-access-split.py --v3
97+
8898
- name: Run ${{ matrix.benchmark.name }} benchmark
99+
if: matrix.benchmark.id != 'random-access-bench'
89100
shell: bash
90101
env:
91102
RUST_BACKTRACE: full

benchmarks/datafusion-bench/src/lib.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,7 @@ pub fn get_session_context() -> SessionContext {
4545
.build_arc()
4646
.expect("could not build runtime environment");
4747

48-
let factory = VortexFormatFactory::new().with_options(VortexTableOptions {
49-
projection_pushdown: true,
50-
..Default::default()
51-
});
48+
let factory = VortexFormatFactory::new().with_options(vortex_table_options());
5249

5350
let mut session_state_builder = SessionStateBuilder::new()
5451
.with_config(SessionConfig::from_env().expect("shouldn't fail"))
@@ -114,11 +111,20 @@ pub fn format_to_df_format(format: Format) -> Arc<dyn FileFormat> {
114111
Format::Csv => Arc::new(CsvFormat::default()) as _,
115112
Format::Arrow => Arc::new(ArrowFormat),
116113
Format::Parquet => Arc::new(ParquetFormat::new()),
117-
Format::OnDiskVortex | Format::VortexCompact => {
118-
Arc::new(VortexFormat::new(SESSION.clone()))
119-
}
114+
Format::OnDiskVortex | Format::VortexCompact => Arc::new(VortexFormat::new_with_options(
115+
SESSION.clone(),
116+
vortex_table_options(),
117+
)),
120118
Format::OnDiskDuckDB | Format::Lance => {
121119
unimplemented!("Format {format} cannot be turned into a DataFusion `FileFormat`")
122120
}
123121
}
124122
}
123+
124+
fn vortex_table_options() -> VortexTableOptions {
125+
VortexTableOptions {
126+
projection_pushdown: true,
127+
predicate_pushdown: true,
128+
..Default::default()
129+
}
130+
}

docs/developer-guide/internals/execution.md

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -115,21 +115,28 @@ Each child is given the opportunity to execute its parent in a fused manner via
115115
`ExecuteParentKernel`. Unlike reduce rules, parent kernels may read buffers and perform real
116116
computation.
117117

118-
An encoding declares its parent kernels in a `ParentKernelSet`, specifying which parent types
119-
each kernel handles via a `Matcher`:
118+
An encoding declares parent kernels by implementing `ExecuteParentKernel` and registering them
119+
with the session-scoped kernel registry, specifying which parent types each kernel handles via a
120+
`Matcher`:
120121

121122
```rust
122123
pub trait ExecuteParentKernel<V: VTable> {
123124
type Parent: Matcher; // which parent types this kernel handles
124125

125126
fn execute_parent(
126127
&self,
127-
array: &V::Array, // the child
128+
array: ArrayView<'_, V>, // the child
128129
parent: <Self::Parent as Matcher>::Match<'_>, // the matched parent
129130
child_idx: usize,
130131
ctx: &mut ExecutionCtx,
131132
) -> VortexResult<Option<ArrayRef>>;
132133
}
134+
135+
pub fn initialize(session: &VortexSession) {
136+
session
137+
.kernels()
138+
.register_execute_parent_kernel(parent_id, Child, Kernel);
139+
}
133140
```
134141

135142
Examples:
@@ -195,17 +202,23 @@ execute_until<M>(root):
195202
│ restore builder, │
196203
│ loop ▼
197204
│ ┌────────────────────────────────────────────┐
198-
│ │ Step 2a: current_array.execute_parent( │
199-
│ │ stack.top.parent_array ) │
200-
│ │ child looks UP at the suspended parent │
205+
│ │ Step 2a: execute_parent_for_child( │
206+
│ │ stack.top.parent_array, │
207+
│ │ current_array ) │
208+
│ │ lookup session kernels by key: │
209+
│ │ (parent.encoding_id(), │
210+
│ │ child.encoding_id()) │
201211
│ ├────────────┬───────────────────────────────┘
202212
│ │ Some │ None
203213
│ │ │
204214
│ │ ▼
205215
│ │ ┌─────────────────────────────────────────┐
206-
│ │ │ Step 2b: each child.execute_parent( │
207-
│ │ │ current_array ) │
208-
│ │ │ children look UP at current_array │
216+
│ │ │ Step 2b: for each child: │
217+
│ │ │ execute_parent_for_child( │
218+
│ │ │ current_array, child ) │
219+
│ │ │ lookup session kernels by key: │
220+
│ │ │ (parent.encoding_id(), │
221+
│ │ │ child.encoding_id()) │
209222
│ │ ├──────────┬──────────────────────────────┘
210223
│ │ │ Some │ None
211224
│ │ │ │
@@ -236,6 +249,9 @@ Step 2a and Step 2b are skipped while `current_builder` is active. `AppendChild`
236249
consumes `current_array`: some slots already live in the builder, so a parent rewrite would
237250
observe inconsistent state and could discard accumulated builder data.
238251

252+
Both Step 2a and Step 2b route through `execute_parent_for_child`, which looks up
253+
`(parent.encoding_id(), child.encoding_id())` in the session kernel snapshot.
254+
239255
## Incremental Execution
240256

241257
Execution is incremental: each call to `execute` moves the array one step closer to canonical
@@ -256,12 +272,12 @@ codes through the slice, missing the Dict-RLE optimization entirely. Incremental
256272
avoids this:
257273

258274
1. First iteration: the slice `execute` returns `ExecuteSlot` for its `RunEndArray` child.
259-
Once that child is in focus, Step 2a gives it a chance to rewrite the suspended slice
260-
parent before the child is forced toward canonical form.
275+
Once that child is in focus, Step 2a looks up a registered parent kernel for the
276+
`(slice, runend)` pair before the child is forced toward canonical form.
261277

262278
2. Second iteration: the `RunEndArray` codes child now matches the Dict-RLE pattern. Its
263-
`execute_parent` provides a fused kernel that expands runs while performing dictionary
264-
lookups in a single pass, returning the canonical array directly.
279+
registered execute-parent kernel expands runs while performing dictionary lookups in a single
280+
pass, returning the canonical array directly.
265281

266282
## Walkthrough: Executing a RunEnd-Encoded Array
267283

encodings/alp/benches/alp_compress.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ const BENCH_ARGS: &[(usize, f64, f64)] = &[
5050
(10_000, 0.1, 1.0),
5151
];
5252

53-
static SESSION: LazyLock<VortexSession> = LazyLock::new(vortex_array::array_session);
53+
static SESSION: LazyLock<VortexSession> = LazyLock::new(|| {
54+
let session = vortex_array::array_session();
55+
vortex_alp::initialize(&session);
56+
session
57+
});
5458

5559
#[divan::bench(types = [f32, f64], args = BENCH_ARGS)]
5660
fn compress_alp<T: ALPFloat + NativePType>(bencher: Bencher, args: (usize, f64, f64)) {

encodings/alp/src/alp/array.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ use vortex_session::registry::CachedId;
4848
use crate::ALPFloat;
4949
use crate::alp::Exponents;
5050
use crate::alp::decompress::execute_decompress;
51-
use crate::alp::rules::PARENT_KERNELS;
5251
use crate::alp::rules::RULES;
5352

5453
/// A [`ALP`]-encoded Vortex array.
@@ -188,15 +187,6 @@ impl VTable for ALP {
188187
) -> VortexResult<Option<ArrayRef>> {
189188
RULES.evaluate(array, parent, child_idx)
190189
}
191-
192-
fn execute_parent(
193-
array: ArrayView<'_, Self>,
194-
parent: &ArrayRef,
195-
child_idx: usize,
196-
ctx: &mut ExecutionCtx,
197-
) -> VortexResult<Option<ArrayRef>> {
198-
PARENT_KERNELS.execute(array, parent, child_idx, ctx)
199-
}
200190
}
201191

202192
#[array_slots(ALP)]

encodings/alp/src/alp/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,14 @@ use vortex_array::dtype::NativePType;
6161
use vortex_array::scalar::PValue;
6262
use vortex_buffer::Buffer;
6363
use vortex_buffer::BufferMut;
64+
use vortex_session::VortexSession;
6465

6566
const SAMPLE_SIZE: usize = 32;
6667

68+
pub(crate) fn initialize(session: &VortexSession) {
69+
rules::initialize(session);
70+
}
71+
6772
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
6873
pub struct Exponents {
6974
pub e: u8,

encodings/alp/src/alp/rules.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

4+
use vortex_array::ArrayVTable;
5+
use vortex_array::arrays::Dict;
6+
use vortex_array::arrays::Filter;
7+
use vortex_array::arrays::Slice;
48
use vortex_array::arrays::dict::TakeExecuteAdaptor;
59
use vortex_array::arrays::filter::FilterExecuteAdaptor;
610
use vortex_array::arrays::slice::SliceExecuteAdaptor;
7-
use vortex_array::kernel::ParentKernelSet;
11+
use vortex_array::optimizer::kernels::ArrayKernelsExt;
812
use vortex_array::optimizer::rules::ParentRuleSet;
13+
use vortex_array::scalar_fn::ScalarFnVTable;
914
use vortex_array::scalar_fn::fns::between::BetweenReduceAdaptor;
15+
use vortex_array::scalar_fn::fns::binary::Binary;
1016
use vortex_array::scalar_fn::fns::binary::CompareExecuteAdaptor;
1117
use vortex_array::scalar_fn::fns::cast::CastReduceAdaptor;
18+
use vortex_array::scalar_fn::fns::mask::Mask;
1219
use vortex_array::scalar_fn::fns::mask::MaskExecuteAdaptor;
1320
use vortex_array::scalar_fn::fns::mask::MaskReduceAdaptor;
21+
use vortex_session::VortexSession;
1422

1523
use crate::ALP;
1624

17-
pub(super) const PARENT_KERNELS: ParentKernelSet<ALP> = ParentKernelSet::new(&[
18-
ParentKernelSet::lift(&CompareExecuteAdaptor(ALP)),
19-
ParentKernelSet::lift(&FilterExecuteAdaptor(ALP)),
20-
ParentKernelSet::lift(&MaskExecuteAdaptor(ALP)),
21-
ParentKernelSet::lift(&SliceExecuteAdaptor(ALP)),
22-
ParentKernelSet::lift(&TakeExecuteAdaptor(ALP)),
23-
]);
25+
pub(super) fn initialize(session: &VortexSession) {
26+
let kernels = session.kernels();
27+
kernels.register_execute_parent_kernel(Binary.id(), ALP, CompareExecuteAdaptor(ALP));
28+
kernels.register_execute_parent_kernel(Filter.id(), ALP, FilterExecuteAdaptor(ALP));
29+
kernels.register_execute_parent_kernel(Mask.id(), ALP, MaskExecuteAdaptor(ALP));
30+
kernels.register_execute_parent_kernel(Slice.id(), ALP, SliceExecuteAdaptor(ALP));
31+
kernels.register_execute_parent_kernel(Dict.id(), ALP, TakeExecuteAdaptor(ALP));
32+
}
2433

2534
pub(super) const RULES: ParentRuleSet<ALP> = ParentRuleSet::new(&[
2635
ParentRuleSet::lift(&BetweenReduceAdaptor(ALP)),

encodings/alp/src/alp_rd/array.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ use vortex_error::vortex_panic;
5353
use vortex_session::VortexSession;
5454
use vortex_session::registry::CachedId;
5555

56-
use crate::alp_rd::kernel::PARENT_KERNELS;
5756
use crate::alp_rd::rules::RULES;
5857
use crate::alp_rd_decode;
5958

@@ -307,15 +306,6 @@ impl VTable for ALPRD {
307306
) -> VortexResult<Option<ArrayRef>> {
308307
RULES.evaluate(array, parent, child_idx)
309308
}
310-
311-
fn execute_parent(
312-
array: ArrayView<'_, Self>,
313-
parent: &ArrayRef,
314-
child_idx: usize,
315-
ctx: &mut ExecutionCtx,
316-
) -> VortexResult<Option<ArrayRef>> {
317-
PARENT_KERNELS.execute(array, parent, child_idx, ctx)
318-
}
319309
}
320310

321311
/// The left (most significant) parts of the real-double encoded values.

encodings/alp/src/alp_rd/kernel.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

4+
use vortex_array::ArrayVTable;
5+
use vortex_array::arrays::Dict;
6+
use vortex_array::arrays::Filter;
7+
use vortex_array::arrays::Slice;
48
use vortex_array::arrays::dict::TakeExecuteAdaptor;
59
use vortex_array::arrays::filter::FilterExecuteAdaptor;
610
use vortex_array::arrays::slice::SliceExecuteAdaptor;
7-
use vortex_array::kernel::ParentKernelSet;
11+
use vortex_array::optimizer::kernels::ArrayKernelsExt;
12+
use vortex_session::VortexSession;
813

914
use crate::alp_rd::ALPRD;
1015

11-
pub(crate) static PARENT_KERNELS: ParentKernelSet<ALPRD> = ParentKernelSet::new(&[
12-
ParentKernelSet::lift(&SliceExecuteAdaptor(ALPRD)),
13-
ParentKernelSet::lift(&FilterExecuteAdaptor(ALPRD)),
14-
ParentKernelSet::lift(&TakeExecuteAdaptor(ALPRD)),
15-
]);
16+
pub(crate) fn initialize(session: &VortexSession) {
17+
let kernels = session.kernels();
18+
kernels.register_execute_parent_kernel(Slice.id(), ALPRD, SliceExecuteAdaptor(ALPRD));
19+
kernels.register_execute_parent_kernel(Filter.id(), ALPRD, FilterExecuteAdaptor(ALPRD));
20+
kernels.register_execute_parent_kernel(Dict.id(), ALPRD, TakeExecuteAdaptor(ALPRD));
21+
}

0 commit comments

Comments
 (0)