Stamps at the batch-to-records seams, leave_dynamic under multi-element stamps, and unconsolidated feedback - #855
Open
frankmcsherry wants to merge 6 commits into
Open
Stamps at the batch-to-records seams, leave_dynamic under multi-element stamps, and unconsolidated feedback#855frankmcsherry wants to merge 6 commits into
frankmcsherry wants to merge 6 commits into
Conversation
Both the row and the corgi `leave_dynamic` read `cap.time()`, which now
panics ("expected a singleton stamp") when a message carries timestamps
from two epochs — late iterations of one alongside early ones of the next,
which any steady-state run of an iterative program produces. Hold a
capability per stamp element, each truncated exactly as the records are,
and open the session on the set.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012k2GSwxmvD2LvckkoXi6GK
The round loop churned synthetic rows from `gen_row`, which with a file-fed input meant retracting rows the dataflow never saw and inserting random ones (duplicate ids, cycles). Each update now retracts one of the file's rows and re-inserts it with its last field rewired below its first, so a round is an edit to data the dataflow holds. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012k2GSwxmvD2LvckkoXi6GK
compare_idx and gather read sum discriminants in place (WIP master 3c4b0d6f), which is what took the e-graph's 200k-node saturation from 43s to 23s on the corgi backend. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012k2GSwxmvD2LvckkoXi6GK
…a program An iteration quiesces when its feedback carries no records, so a var whose step's additions and retractions cancel only logically — a `negate` under a `concat` — never quiesced: the vec backend ran forever on a program whose fixpoint was reached in one round. Every var is now set to its consolidated step (`Backend::consolidate`, through the arrangement by default). The suite's timings are unchanged; the programs there all fed their vars through a reduce, which consolidated by nature. tests/identifiers.rs writes DD's `identifiers` algorithm in DDIR: each record proposes hash(round, record); among the proposers of an id the least (round, record) wins and the losers try the next round; with hash, min, negate and a var, over 64 slots for 32 records, every record gets its own id (25 settle at round 0, the rest by round 4). It is the primitive an e-graph rule needs to mint a node for a new term inside the program. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012k2GSwxmvD2LvckkoXi6GK
…messages come from Instrumenting the batch-shipping operators on the run that panicked (a DDIR program at 20k nodes, four workers, epochs fed without waiting) shows the multi-element stamps being minted: an arrange retiring (1, [18]) and (2, []) — epoch 1 at round 18 alongside epoch 2 just entered — in one batch, then a join forwarding its input batch's set, then a reduce retiring the same pair, and finally an arrange whose batch, forwarded by as_collection under the retiring set and delayed element-wise by the feedback, reached the scope's exit as (1, [19]), (2, [1]). Which retirements coincide depends on scheduling, so the test makes the message directly: an operator that ships its input under a capability for epoch e round 3 and one for epoch e + 1 round 0, into leave_dynamic. It panics with "expected a singleton stamp" before this branch's fix and passes with it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012k2GSwxmvD2LvckkoXi6GK
…ount, threshold route by time A batch is shipped under the set of capabilities it retires, so a message of batches carries several timestamps when two epochs retire together. The operators that turn batches back into records forwarded the records under that same set, which is how a multi-element stamp reached `leave_dynamic` and anything else that reads a message's time as one. `StampRouter` (collection.rs) gives one capability per element of a message's stamp and routes each record to the first element at or before its time (a batch's times are at or beyond one of the capabilities it retired under, so every record has one). It is applied at every seam that makes records from batches: the vec `as_collection` (`flat_map_batches`), `count`, `threshold`, the columnar `as_recorded_updates`, and DDIR's corgi `as_collection` (a chunk under one capability goes whole, as before; under several it is split by row). With that, a collection's messages carry one timestamp each; only streams of batches carry sets. Not routed: `join_with_tactic`'s output, whose tactic builds containers the operator cannot split by time (the fix belongs in the tactics, a builder per element of the fresh batch's set), and `as_container`, which forwards opaque containers. `leave_dynamic` keeps holding a capability per element, so it is safe either way. tests/dynamic.rs: a hand-built batch under capabilities for epoch 0 round 3 and epoch 1 round 0, through `as_collection` into an operator that reads each message's time as one, lands its records in their two epochs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012k2GSwxmvD2LvckkoXi6GK
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two bugs found while running DDIR programs in steady state, the seam that let the first one through, and the driver edit mode and corgi pin that surfaced them.
Where multi-element stamps come from, and where they were leaking. Since timely #813 a message's stamp is a multiset, and DD's batch-shipping operators make multi-element ones:
arrangeships each batch under the set of capabilities it retires,reducelikewise,joinforwards its input batch's set. In an iterative scope with two epochs in flight, an arrange holding(1, [18])(epoch 1, round 18) and(2, [])(epoch 2, just entered) retires both in one batch when its input frontier passes both at once. Instrumenting the operators on the run that panicked (a DDIR program at 20k nodes, four workers, epochs fed without waiting) shows the chain: an arrange minted the first multi-element stamp, then a join, then a reduce, then an arrange whose batch reached the scope's exit as(1, [19]), (2, [1]).The leak was the seam from batches to records:
as_collectionforwarded a batch's records under the batch's set, so a collection carried messages whose capability spanned two epochs though no record did, and anything reading a message's time as one,cap.time(), panicked with "expected a singleton stamp".StampRouter(collection.rs) now gives one capability per element of a message's stamp and routes each record to the first element at or before its time; it is applied at every seam that makes records from batches: the vecas_collection,count,threshold, the columnaras_recorded_updates, and DDIR's corgias_collection. With that, collection streams carry one timestamp per message and only batch streams carry sets. Not yet routed:join_with_tactic's output, whose tactics build containers the operator cannot split (the fix belongs in the tactics, a builder per element), andas_container(opaque containers, no users found).tests/dynamic.rschecks the seam with a hand-built batch under two epochs' capabilities.leave_dynamicitself. All three (DD's row and columnar collections, DDIR's corgi backend) readcap.time()to truncate it. Each now holds a capability per stamp element, truncated exactly as the records are, and opens its session on the set, so it is safe whatever reaches it; a test makes the two-epoch message directly, panics before the fix and passes with it. An audit of DD, DDIR, and dogsdogsdogs found no otherInputCapability::time()reads.Unconsolidated feedback. A DDIR
varwas set to its step unconsolidated. An iteration quiesces when its feedback carries no records, not when it carries nothing net, so a step whose additions and retractions cancel only logically (anegateunder aconcat) never quiesced: the vec backend ran forever on a program whose fixpoint was reached in one round. Every program in the suite fed its vars through a reduce, which consolidates by nature, so nothing had seen it. Each var is now set to its consolidated step (Backend::consolidate, through the arrangement by default); the suite's timings are unchanged. The regression test is DD'sidentifiersalgorithm written as a DDIR program (interactive/tests/identifiers.rs): hash, min, negate, and a var give 32 records unique ids over 64 slots.The
ddirdriver's rounds edit file-fed rows. WithEDGES_FILE, the round loop used to churn synthetic rows the dataflow never saw. Each update now retracts one of the file's rows and re-inserts it with its last field rewired, so a round is an edit to data the dataflow holds.corgi pinned at WIP
3c4b0d6f, wherecompare_idxandgatherread sum discriminants in place (43s -> 23s on a 200k-node saturation).🤖 Generated with Claude Code
https://claude.ai/code/session_012k2GSwxmvD2LvckkoXi6GK