Skip to content

Few minor fixes and optimization#367

Open
fereidani wants to merge 3 commits into
egraphs-good:mainfrom
fereidani:main
Open

Few minor fixes and optimization#367
fereidani wants to merge 3 commits into
egraphs-good:mainfrom
fereidani:main

Conversation

@fereidani

Copy link
Copy Markdown

Hey, awesome project! I'm building a super-optimizer on top of it+Z3, and I've had a great experience using it. Here's my performance optimization PR results:

find_costs performance: old vs new

Benchmark of Extractor::new (which runs all of find_costs) on EGraph<SymbolLang, ()> with the AstSize cost function. Measured with criterion over 100 samples.

  • Original = find_costs: repeated full-scan fixpoint until no cost changes, cloning the chosen node into the costs map on every pass.
  • New = new src/extract.rs: worklist-based find_costs (costs propagate only to parents on change) and stores the e-node's index into EClass::nodes instead of cloning the node.
Scenario Original (fixpoint + clone) Latest (worklist + no-clone) Speedup
deep_chain/200 693.12 µs [688.87, 698.47] 21.38 µs [20.40, 22.35] 32×
deep_chain/2000 43.12 ms [42.70, 43.58] 174.43 µs [173.91, 174.95] 247×
deep_chain/20000 9.14 s [8.87, 9.43] 1.94 ms [1.93, 1.96] 4707×
wide_tree/256leaves 112.95 µs [112.05, 113.87] 30.09 µs [30.02, 30.17] 3.8×
wide_tree/4096leaves 4.39 ms [4.24, 4.59] 787.36 µs [757.42, 829.71] 5.6×
wide_tree/16384leaves 30.27 ms [29.04, 31.57] 6.82 ms [6.29, 7.36] 4.4×
saturated/491classes 324.11 µs [313.86, 337.23] 102.24 µs [101.75, 102.86] 3.2×
saturated/1121classes 1.37 ms [1.36, 1.39] 715.27 µs [712.69, 717.90] 1.9×
saturated/10455classes 12.28 ms [11.84, 12.73] 6.68 ms [6.52, 6.84] 1.8×

Scenarios

  • deep_chain/N: a right-nested chain (f (f (f … a))) of depth N. A single long cost-dependency chain. Worst case for the old algorithm.
  • wide_tree/Nleaves: a complete balanced binary tree of + over N distinct leaves. Shallow and wide.
  • saturated/…: a realistic e-graph produced by running associativity, commutativity, distributivity/factoring, and identity rewrites on (* (+ a b) (* (+ c d) (* (+ e f) (+ g h)))) to saturation with a node budget. The shape find_costs sees in real use.

@mwillsey

Copy link
Copy Markdown
Member

Hi, thanks for the contribution. Have you seen the https://github.com/egraphs-good/extraction-gym? Does this algorithm related to any of those?

@fereidani

Copy link
Copy Markdown
Author

Thank you for your response, I just checked extraction-gym and Yes, it relates directly, the worklist part of this PR is essentially the gym's faster-bottom-up extractor (dedup FIFO of pending work, re-enqueue parents when a class's best cost improves), and the code it replaces corresponds to the bottom-up baseline (full re-scan fixpoint). Both are tree-cost extractors, so the extraction result is unchanged, and this PR doesn't attempt anything from the DAG-cost or ILP families.

The PR has a second part the gym doesn't cover: Extractor::costs used to store (Cost, L), a clone of the winning e-node, re-cloned on every improving pass, and now stores (Cost, usize), the node's index in its e-class, resolved back to &L on demand. That's the same id-based bookkeeping the gym's extractors use for their ClassId to NodeId choices, but applied inside egg's Extractor, so it also cuts allocations and the memory held per class. The gym benchmarks standalone extractors over serialized e-graphs, so this in-library effect wouldn't show up there. The table in the description reflects both that the asymptotic win from the worklist on deep e-graphs and the constant-factor/memory win from not cloning.

One caveat is that with a FIFO worklist a class can re-relax on cyclic e-graphs, so linear time is the practical bound rather than a strict guarantee, the gym's prio-queue variant(cheapest-first, each class settles exactly once) is the strict version. I kept FIFO here since it's the smallest change to egg's existing make_pass/parents structure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants