Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
4a25840
Prototype arena-backed ArenaNode
MilesCranmerBot Feb 1, 2026
5cb2644
Add reusable ArenaCursor preorder traversal
MilesCranmerBot Feb 1, 2026
75831c8
Add postfix stack-based utilities inspired by symbolic_regression.rs
MilesCranmerBot Feb 1, 2026
609e402
Add postfix validity check
MilesCranmerBot Feb 1, 2026
d7391a7
ArenaNode: postfix roundtrip + minimal commutative rewrite
MilesCranmerBot Feb 1, 2026
c77cf83
docs/tests: clarify postfix utilities are for roundtrips only
MilesCranmerBot Feb 1, 2026
8d8755c
ArenaNode: allow cross-arena set_child!/set_children! via copy
MilesCranmerBot Feb 1, 2026
8bb1b22
ArenaNode: traversal-based postfix emit + cursor-based rewrite
MilesCranmerBot Feb 2, 2026
da69782
fix: stabilize ArenaNode prototype traversal and tests
MilesCranmerBot Feb 20, 2026
0c9770a
fix: stabilize ArenaNode follow-up
MilesCranmerBot Jun 9, 2026
d1f6ec4
fix: evaluate ArenaNode directly
MilesCranmerBot Jun 10, 2026
bc8df59
fix: stabilize ArenaNode CI follow-up
MilesCranmerBot Jun 10, 2026
85ba708
test: expand ArenaNode interface coverage
MilesCranmerBot Jun 10, 2026
b3454b1
chore: restore compat bounds
MilesCranmerBot Jun 10, 2026
f7b6e54
style: format ArenaNode follow-up
MilesCranmerBot Jun 10, 2026
54c77f0
fix: revert is_constant rewrite
MilesCranmerBot Jun 10, 2026
feff122
test(ArenaNode): add Expression interface and derivative tests
MilesCranmerBot Jun 10, 2026
b284917
fix: stabilize ArenaNode follow-up CI
MilesCranmerBot Jun 11, 2026
23be071
fix: address ArenaNode review cleanup
MilesCranmerBot Jun 11, 2026
bd312ed
fix: stabilize ArenaNode CI dependencies
MilesCranmerBot Jun 11, 2026
75e947c
fix: remove ArenaNode postfix debug utilities
MilesCranmerBot Jun 11, 2026
d15946c
fix: keep LoweredCodeUtils test bound tight
MilesCranmerBot Jun 11, 2026
445a88f
fix: allow Julia 1.10 JET test compat
MilesCranmerBot Jun 11, 2026
7d6d295
fix: stabilize ArenaNode CI checks
MilesCranmerBot Jun 11, 2026
f780188
fix: raise SymbolicUtils lower bound
MilesCranmerBot Jun 11, 2026
a5ebf50
fix: constrain downgrade test dependencies
MilesCranmerBot Jun 11, 2026
415cb32
fix: exclude uninstrumented extension coverage
MilesCranmerBot Jun 11, 2026
07fca1b
fix: address ArenaNode review comments
MilesCranmerBot Jun 11, 2026
8556b1a
fix: restore default Aqua checks
MilesCranmerBot Jun 11, 2026
a44279d
fix: simplify get_child integer dispatch
MilesCranmerBot Jun 11, 2026
14fffe7
feat: optimize ArenaNode storage and copies
MilesCranmerBot Jun 11, 2026
11ea817
fix: speed up ArenaNode traversals
MilesCranmerBot Jun 12, 2026
e4aa364
feat: add iterative ArenaNode eval
MilesCranmerBot Jun 12, 2026
676be78
fix: stabilize ArenaNode tests
MilesCranmerBot Jun 12, 2026
4c249da
feat: add buffered ArenaNode plan evaluator
MilesCranmerBot Jun 12, 2026
9edfa04
refactor(ArenaNode): generalize buffered plan evaluation to arbitrary…
MilesCranmer Jun 12, 2026
30e2d76
test: revert Aqua workaround (belongs in a separate PR)
MilesCranmer Jun 12, 2026
cc9863a
fix(ArenaNode): close review findings on safety and Node parity
MilesCranmer Jun 12, 2026
514172f
refactor(ArenaNode): bundle plan-eval state into _PlanState/_PlanRegs
MilesCranmer Jun 12, 2026
ae0a41d
refactor(ArenaNode): self-documenting variable names
MilesCranmer Jun 12, 2026
f2194a1
refactor(ArenaNode): address review comments
MilesCranmer Jun 12, 2026
43cd969
refactor(ArenaNode): flatten _exec_op! into guard-clause helpers
MilesCranmer Jun 12, 2026
8672eb1
refactor(ArenaNode): replace out() thunk with a plain output view bin…
MilesCranmer Jun 12, 2026
a61fd13
refactor(ArenaNode): share child attachment via _resolve_child_index!
MilesCranmer Jun 12, 2026
942d502
refactor(ArenaNode): single-source the planner/executor slot policy
MilesCranmer Jun 12, 2026
4a681de
refactor(ArenaNode): named raw accessors instead of getfield; restore…
MilesCranmer Jun 12, 2026
f3b361d
refactor(ArenaNode): name the descriptor bit operations
MilesCranmer Jun 12, 2026
7d2685b
perf(ArenaNode): recover base validation cost without losing ok parity
MilesCranmer Jun 12, 2026
1719186
refactor(ArenaNode): OperandKind enum for descriptor kinds
MilesCranmer Jun 12, 2026
13e0a6f
Revert "refactor(ArenaNode): OperandKind enum for descriptor kinds"
MilesCranmer Jun 12, 2026
4e2536c
docs(ArenaNode): plain comments instead of docstrings on internals
MilesCranmer Jun 12, 2026
bf98235
style(ArenaNode): drop ceremonial @inline; flatten repeated returns
MilesCranmer Jun 12, 2026
6e9c522
perf(ArenaNode): keep @inline on setproperty!
MilesCranmer Jun 12, 2026
9a5957e
bench(ArenaNode): also measure the unbuffered paths
MilesCranmer Jun 12, 2026
cb580c8
refactor(ArenaNode): split the plan evaluator into ArenaNodeEval.jl
MilesCranmer Jun 12, 2026
bcd6a53
fix(ArenaNode): CI fixes, override deletion, facade poison guard, fas…
MilesCranmer Jun 12, 2026
13e04eb
test(ArenaNode): Supposition invariants
MilesCranmer Jun 12, 2026
2bdc96c
perf(ArenaNode): direct entry recursion for hash; flat count_constant…
MilesCranmer Jun 12, 2026
56b1f3b
perf(ArenaNode): entry-level tree_mapreduce skeleton
MilesCranmer Jun 12, 2026
26e2c7c
perf(ArenaNode): entry-level recursion for non-compact any
MilesCranmer Jun 12, 2026
f89e77f
docs(ArenaNode): record why tree_mapreduce keeps recursion
MilesCranmer Jun 12, 2026
aad9a1f
refactor(ArenaNode): one body for compact and non-compact any
MilesCranmer Jun 12, 2026
d1720cb
perf(ArenaNode): _foreach_node iteration driver; flat ==; faster cons…
MilesCranmer Jun 12, 2026
2cba5f7
test(ArenaNode): avoid Data.OneOf in the mutation generator
MilesCranmer Jun 12, 2026
2ca00ca
test: raise downgraded test dependency bounds
MilesCranmerBot Jun 13, 2026
9850b0b
fix: address ArenaNode API regressions
MilesCranmerBot Jun 14, 2026
2846c3b
Merge master into arenanode-prototype
MilesCranmerBot Aug 8, 2026
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
89 changes: 89 additions & 0 deletions scripts/bench_arenanode_eval.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using DynamicExpressions
using DynamicExpressions: EvalOptions, ArrayBuffer
using Random: MersenneTwister

include(joinpath(@__DIR__, "..", "test", "tree_gen_utils.jl"))

const AN = DynamicExpressions.ArenaNodeModule

operators = OperatorEnum(1 => (cos, exp), 2 => (+, -, *, /))
const T = Float64
nfeat = 5
n = 1_000
rng = MersenneTwister(0)
X = randn(rng, T, nfeat, n)
buf = zeros(T, 64, n)

function bench(trees, X, operators, buffer; reps=300)
best = Inf
for _ in 1:reps
t0 = time_ns()
for tree in trees
buffer.index[] = 0
eval_tree_array(tree, X, operators; eval_options=EvalOptions(; buffer))
end
best = min(best, (time_ns() - t0) / length(trees))
end
return best
end

function allocs_per_eval(tree, X, operators, buffer)
@allocated(eval_tree_array(tree, X, operators; eval_options=EvalOptions(; buffer)))
end

for treesize in (7, 15, 31)
trees = [gen_random_tree_fixed_size(treesize, operators, nfeat, T) for _ in 1:50]
atrees = [convert(AN.ArenaNode{T,2}, t) for t in trees]
buffer = ArrayBuffer(buf, Ref(0))

# correctness sanity: both paths must agree
for (t, a) in zip(trees, atrees)
buffer.index[] = 0
yn, okn = eval_tree_array(t, X, operators; eval_options=EvalOptions(; buffer))
buffer.index[] = 0
ya, oka = eval_tree_array(a, X, operators; eval_options=EvalOptions(; buffer))
okn == oka || error("ok mismatch at size $treesize")
okn && (yn ≈ ya || error("value mismatch at size $treesize"))
end

# warmup
bench(trees, X, operators, buffer; reps=3)
bench(atrees, X, operators, buffer; reps=3)

t_node = bench(trees, X, operators, buffer)
t_arena = bench(atrees, X, operators, buffer)
buffer.index[] = 0
a_node = allocs_per_eval(trees[1], X, operators, buffer)
buffer.index[] = 0
a_arena = allocs_per_eval(atrees[1], X, operators, buffer)
println(
"n=$treesize Node: $(round(t_node/1e3; digits=2))us " *
"ArenaNode: $(round(t_arena/1e3; digits=2))us " *
"ratio=$(round(t_arena/t_node; digits=3)) " *
"allocs/eval Node=$a_node Arena=$a_arena",
)

bench_nobuf(trees) = begin
best = Inf
for _ in 1:300
t0 = time_ns()
for tree in trees
eval_tree_array(tree, X, operators)
end
best = min(best, (time_ns() - t0) / length(trees))
end
best
end
bench_nobuf(trees[1:2])
bench_nobuf(atrees[1:2]) # warmup
tn_nb = bench_nobuf(trees)
ta_nb = bench_nobuf(atrees)
an_nb = @allocated(eval_tree_array(trees[1], X, operators))
aa_nb = @allocated(eval_tree_array(atrees[1], X, operators))
println(
"n=$treesize unbuffered: Node: $(round(tn_nb/1e3; digits=2))us " *
"ArenaNode: $(round(ta_nb/1e3; digits=2))us " *
"ratio=$(round(ta_nb/tn_nb; digits=3)) " *
"allocs/eval Node=$an_nb Arena=$aa_nb",
)
end
Loading
Loading