Skip to content

Commit cdebcdc

Browse files
feat: iterative execution (#7335)
use iterative execution in vortex array --------- Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
1 parent d72bf9b commit cdebcdc

11 files changed

Lines changed: 60 additions & 61 deletions

File tree

encodings/alp/src/alp/array.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ impl VTable for ALP {
172172
let array = require_child!(array, array.encoded(), ENCODED_SLOT => Primitive);
173173
require_patches!(
174174
array,
175-
array.patches(),
176175
PATCH_INDICES_SLOT,
177176
PATCH_VALUES_SLOT,
178177
PATCH_CHUNK_OFFSETS_SLOT

encodings/alp/src/alp_rd/array.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,6 @@ impl VTable for ALPRD {
228228
let array = require_child!(array, array.right_parts(), 1 => Primitive);
229229
require_patches!(
230230
array,
231-
array.left_parts_patches(),
232231
LP_PATCH_INDICES_SLOT,
233232
LP_PATCH_VALUES_SLOT,
234233
LP_PATCH_CHUNK_OFFSETS_SLOT

encodings/fastlanes/src/bitpacking/vtable/mod.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use std::hash::Hash;
55
use std::hash::Hasher;
66

77
use prost::Message;
8-
use vortex_array::AnyCanonical;
98
use vortex_array::Array;
109
use vortex_array::ArrayEq;
1110
use vortex_array::ArrayHash;
@@ -283,17 +282,11 @@ impl VTable for BitPacked {
283282
fn execute(array: Array<Self>, ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult> {
284283
require_patches!(
285284
array,
286-
array.patches(),
287285
PATCH_INDICES_SLOT,
288286
PATCH_VALUES_SLOT,
289287
PATCH_CHUNK_OFFSETS_SLOT
290288
);
291-
let validity = array.validity()?;
292-
require_validity!(
293-
array,
294-
&validity,
295-
VALIDITY_SLOT => AnyCanonical
296-
);
289+
require_validity!(array, VALIDITY_SLOT);
297290

298291
Ok(ExecutionResult::done(
299292
unpack_array(array.as_view(), ctx)?.into_array(),

vortex-array/public-api.lock

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4098,7 +4098,7 @@ pub fn vortex_array::arrays::slice::Slice::child_name(array: vortex_array::Array
40984098

40994099
pub fn vortex_array::arrays::slice::Slice::deserialize(&self, _dtype: &vortex_array::dtype::DType, _len: usize, _metadata: &[u8], _buffers: &[vortex_array::buffer::BufferHandle], _children: &dyn vortex_array::serde::ArrayChildren, _session: &vortex_session::VortexSession) -> vortex_error::VortexResult<vortex_array::ArrayParts<Self>>
41004100

4101-
pub fn vortex_array::arrays::slice::Slice::execute(array: vortex_array::Array<Self>, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::ExecutionResult>
4101+
pub fn vortex_array::arrays::slice::Slice::execute(array: vortex_array::Array<Self>, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::ExecutionResult>
41024102

41034103
pub fn vortex_array::arrays::slice::Slice::execute_parent(array: vortex_array::ArrayView<'_, Self>, parent: &vortex_array::ArrayRef, child_idx: usize, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<core::option::Option<vortex_array::ArrayRef>>
41044104

@@ -6496,7 +6496,7 @@ pub fn vortex_array::arrays::slice::Slice::child_name(array: vortex_array::Array
64966496

64976497
pub fn vortex_array::arrays::slice::Slice::deserialize(&self, _dtype: &vortex_array::dtype::DType, _len: usize, _metadata: &[u8], _buffers: &[vortex_array::buffer::BufferHandle], _children: &dyn vortex_array::serde::ArrayChildren, _session: &vortex_session::VortexSession) -> vortex_error::VortexResult<vortex_array::ArrayParts<Self>>
64986498

6499-
pub fn vortex_array::arrays::slice::Slice::execute(array: vortex_array::Array<Self>, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::ExecutionResult>
6499+
pub fn vortex_array::arrays::slice::Slice::execute(array: vortex_array::Array<Self>, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::ExecutionResult>
65006500

65016501
pub fn vortex_array::arrays::slice::Slice::execute_parent(array: vortex_array::ArrayView<'_, Self>, parent: &vortex_array::ArrayRef, child_idx: usize, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<core::option::Option<vortex_array::ArrayRef>>
65026502

@@ -19940,7 +19940,7 @@ pub fn vortex_array::arrays::slice::Slice::child_name(array: vortex_array::Array
1994019940

1994119941
pub fn vortex_array::arrays::slice::Slice::deserialize(&self, _dtype: &vortex_array::dtype::DType, _len: usize, _metadata: &[u8], _buffers: &[vortex_array::buffer::BufferHandle], _children: &dyn vortex_array::serde::ArrayChildren, _session: &vortex_session::VortexSession) -> vortex_error::VortexResult<vortex_array::ArrayParts<Self>>
1994219942

19943-
pub fn vortex_array::arrays::slice::Slice::execute(array: vortex_array::Array<Self>, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::ExecutionResult>
19943+
pub fn vortex_array::arrays::slice::Slice::execute(array: vortex_array::Array<Self>, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::ExecutionResult>
1994419944

1994519945
pub fn vortex_array::arrays::slice::Slice::execute_parent(array: vortex_array::ArrayView<'_, Self>, parent: &vortex_array::ArrayRef, child_idx: usize, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<core::option::Option<vortex_array::ArrayRef>>
1994619946

@@ -20956,7 +20956,7 @@ pub fn vortex_array::arrays::slice::Slice::child_name(array: vortex_array::Array
2095620956

2095720957
pub fn vortex_array::arrays::slice::Slice::deserialize(&self, _dtype: &vortex_array::dtype::DType, _len: usize, _metadata: &[u8], _buffers: &[vortex_array::buffer::BufferHandle], _children: &dyn vortex_array::serde::ArrayChildren, _session: &vortex_session::VortexSession) -> vortex_error::VortexResult<vortex_array::ArrayParts<Self>>
2095820958

20959-
pub fn vortex_array::arrays::slice::Slice::execute(array: vortex_array::Array<Self>, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::ExecutionResult>
20959+
pub fn vortex_array::arrays::slice::Slice::execute(array: vortex_array::Array<Self>, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::ExecutionResult>
2096020960

2096120961
pub fn vortex_array::arrays::slice::Slice::execute_parent(array: vortex_array::ArrayView<'_, Self>, parent: &vortex_array::ArrayRef, child_idx: usize, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<core::option::Option<vortex_array::ArrayRef>>
2096220962

@@ -23660,7 +23660,7 @@ pub fn vortex_array::arrays::slice::Slice::child_name(array: vortex_array::Array
2366023660

2366123661
pub fn vortex_array::arrays::slice::Slice::deserialize(&self, _dtype: &vortex_array::dtype::DType, _len: usize, _metadata: &[u8], _buffers: &[vortex_array::buffer::BufferHandle], _children: &dyn vortex_array::serde::ArrayChildren, _session: &vortex_session::VortexSession) -> vortex_error::VortexResult<vortex_array::ArrayParts<Self>>
2366223662

23663-
pub fn vortex_array::arrays::slice::Slice::execute(array: vortex_array::Array<Self>, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::ExecutionResult>
23663+
pub fn vortex_array::arrays::slice::Slice::execute(array: vortex_array::Array<Self>, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::ExecutionResult>
2366423664

2366523665
pub fn vortex_array::arrays::slice::Slice::execute_parent(array: vortex_array::ArrayView<'_, Self>, parent: &vortex_array::ArrayRef, child_idx: usize, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<core::option::Option<vortex_array::ArrayRef>>
2366623666

@@ -24924,7 +24924,7 @@ pub fn vortex_array::arrays::slice::Slice::child_name(array: vortex_array::Array
2492424924

2492524925
pub fn vortex_array::arrays::slice::Slice::deserialize(&self, _dtype: &vortex_array::dtype::DType, _len: usize, _metadata: &[u8], _buffers: &[vortex_array::buffer::BufferHandle], _children: &dyn vortex_array::serde::ArrayChildren, _session: &vortex_session::VortexSession) -> vortex_error::VortexResult<vortex_array::ArrayParts<Self>>
2492624926

24927-
pub fn vortex_array::arrays::slice::Slice::execute(array: vortex_array::Array<Self>, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::ExecutionResult>
24927+
pub fn vortex_array::arrays::slice::Slice::execute(array: vortex_array::Array<Self>, _ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::ExecutionResult>
2492824928

2492924929
pub fn vortex_array::arrays::slice::Slice::execute_parent(array: vortex_array::ArrayView<'_, Self>, parent: &vortex_array::ArrayRef, child_idx: usize, ctx: &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<core::option::Option<vortex_array::ArrayRef>>
2493024930

vortex-array/src/array/vtable/mod.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,16 @@ pub trait VTable: 'static + Clone + Sized + Send + Sync + Debug {
165165

166166
/// Execute this array by returning an [`ExecutionResult`].
167167
///
168-
/// Instead of recursively executing children, implementations should return
169-
/// [`ExecutionResult::execute_slot`] to request that the scheduler execute a slot first,
170-
/// or [`ExecutionResult::done`] when the encoding can produce a result directly.
168+
/// Execution is **iterative**, not recursive. Instead of recursively executing children,
169+
/// implementations should return [`ExecutionResult::execute_slot`] to request that the
170+
/// scheduler execute a slot first, or [`ExecutionResult::done`] when the encoding can
171+
/// produce a result directly.
172+
///
173+
/// For good examples of this pattern, see:
174+
/// - [`Dict::execute`](crate::arrays::dict::vtable::Dict::execute) — demonstrates
175+
/// requiring children via `require_child!` and producing a result once they are canonical.
176+
/// - `BitPacked::execute` (in `vortex-fastlanes`) — demonstrates requiring patches and
177+
/// validity via `require_patches!`/`require_validity!`.
171178
///
172179
/// Array execution is designed such that repeated execution of an array will eventually
173180
/// converge to a canonical representation. Implementations of this function should therefore

vortex-array/src/arrays/filter/vtable.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ use vortex_error::vortex_panic;
1111
use vortex_mask::Mask;
1212
use vortex_session::VortexSession;
1313

14+
use crate::AnyCanonical;
1415
use crate::ArrayEq;
1516
use crate::ArrayHash;
1617
use crate::ArrayRef;
18+
use crate::Canonical;
1719
use crate::IntoArray;
1820
use crate::Precision;
1921
use crate::array::Array;
@@ -34,6 +36,7 @@ use crate::buffer::BufferHandle;
3436
use crate::dtype::DType;
3537
use crate::executor::ExecutionCtx;
3638
use crate::executor::ExecutionResult;
39+
use crate::require_child;
3740
use crate::scalar::Scalar;
3841
use crate::serde::ArrayChildren;
3942
use crate::validity::Validity;
@@ -142,14 +145,19 @@ impl VTable for Filter {
142145
if let Some(canonical) = execute_filter_fast_paths(array.as_view(), ctx)? {
143146
return Ok(ExecutionResult::done(canonical));
144147
}
145-
let Mask::Values(mask_values) = &array.mask else {
146-
unreachable!("`execute_filter_fast_paths` handles AllTrue and AllFalse")
148+
let mask_values = match &array.mask {
149+
Mask::Values(v) => v.clone(),
150+
_ => unreachable!("`execute_filter_fast_paths` handles AllTrue and AllFalse"),
147151
};
148152

153+
let array = require_child!(array, array.child(), CHILD_SLOT => AnyCanonical);
154+
149155
// We rely on the optimization pass that runs prior to this execution for filter pushdown,
150156
// so now we can just execute the filter without worrying.
157+
// TODO(joe): fix the ownership of AnyCanonical
158+
let child = Canonical::from(array.child().as_::<AnyCanonical>());
151159
Ok(ExecutionResult::done(
152-
execute_filter(array.child().clone().execute(ctx)?, mask_values).into_array(),
160+
execute_filter(child, &mask_values).into_array(),
153161
))
154162
}
155163

vortex-array/src/arrays/masked/vtable/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use vortex_error::vortex_ensure;
1313
use vortex_error::vortex_panic;
1414
use vortex_session::VortexSession;
1515

16+
use crate::AnyCanonical;
1617
use crate::ArrayEq;
1718
use crate::ArrayHash;
1819
use crate::ArrayRef;
@@ -29,12 +30,15 @@ use crate::arrays::masked::MaskedArrayExt;
2930
use crate::arrays::masked::MaskedData;
3031
use crate::arrays::masked::array::CHILD_SLOT;
3132
use crate::arrays::masked::array::SLOT_NAMES;
33+
use crate::arrays::masked::array::VALIDITY_SLOT;
3234
use crate::arrays::masked::compute::rules::PARENT_RULES;
3335
use crate::arrays::masked::mask_validity_canonical;
3436
use crate::buffer::BufferHandle;
3537
use crate::dtype::DType;
3638
use crate::executor::ExecutionCtx;
3739
use crate::executor::ExecutionResult;
40+
use crate::require_child;
41+
use crate::require_validity;
3842
use crate::scalar::Scalar;
3943
use crate::serde::ArrayChildren;
4044
use crate::validity::Validity;
@@ -166,7 +170,10 @@ impl VTable for Masked {
166170
// While we could manually convert the dtype, `mask_validity_canonical` is already O(1) for
167171
// `AllTrue` masks (no data copying), so there's no benefit.
168172

169-
let child = array.child().clone().execute::<Canonical>(ctx)?;
173+
let array = require_child!(array, array.child(), CHILD_SLOT => AnyCanonical);
174+
require_validity!(array, VALIDITY_SLOT);
175+
176+
let child = Canonical::from(array.child().as_::<AnyCanonical>());
170177
Ok(ExecutionResult::done(
171178
mask_validity_canonical(child, &validity_mask, ctx)?.into_array(),
172179
))

vortex-array/src/arrays/patched/vtable/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ impl VTable for Patched {
249249
.execute::<Canonical>(ctx)?
250250
.into_primitive();
251251

252+
// TODO(joe): use iterative execution
252253
let PrimitiveDataParts {
253254
buffer,
254255
ptype,

vortex-array/src/arrays/slice/vtable.rs

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ use crate::AnyCanonical;
1818
use crate::ArrayEq;
1919
use crate::ArrayHash;
2020
use crate::ArrayRef;
21-
use crate::Canonical;
22-
use crate::IntoArray;
2321
use crate::Precision;
2422
use crate::array::Array;
2523
use crate::array::ArrayId;
@@ -36,6 +34,7 @@ use crate::buffer::BufferHandle;
3634
use crate::dtype::DType;
3735
use crate::executor::ExecutionCtx;
3836
use crate::executor::ExecutionResult;
37+
use crate::require_child;
3938
use crate::scalar::Scalar;
4039
use crate::serde::ArrayChildren;
4140
use crate::validity::Validity;
@@ -141,21 +140,13 @@ impl VTable for Slice {
141140
vortex_bail!("Slice array is not serializable")
142141
}
143142

144-
fn execute(array: Array<Self>, ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult> {
145-
// Execute the child to get canonical form, then slice it
146-
let Some(canonical) = array.child().as_opt::<AnyCanonical>() else {
147-
// If the child is not canonical, recurse.
148-
return array
149-
.child()
150-
.clone()
151-
.execute::<ArrayRef>(ctx)?
152-
.slice(array.slice_range().clone())
153-
.map(ExecutionResult::done);
154-
};
143+
fn execute(array: Array<Self>, _ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult> {
144+
let array = require_child!(array, array.child(), CHILD_SLOT => AnyCanonical);
155145

146+
debug_assert!(array.child().is_canonical());
156147
// TODO(ngates): we should inline canonical slice logic here.
157-
Canonical::from(canonical)
158-
.into_array()
148+
array
149+
.child()
159150
.slice(array.range.clone())
160151
.map(ExecutionResult::done)
161152
}

vortex-array/src/compute/conformance/binary_numeric.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,6 @@ where
126126
continue;
127127
};
128128

129-
println!("result {}", result.display_tree());
130-
println!("result {}", result.display_values());
131-
132129
let actual_values = to_vec_of_scalar(&result);
133130

134131
// Check each element for overflow/underflow

0 commit comments

Comments
 (0)