Skip to content

Find products whose factors read three or more relations, as folds of regrouped operands - #130

Closed
alxmrs wants to merge 2 commits into
m3/fill-defaultfrom
m3/regrouped-operands
Closed

alxmrs wants to merge 2 commits into
m3/fill-defaultfrom
m3/regrouped-operands

Conversation

@alxmrs

@alxmrs alxmrs commented Oct 31, 2026 •

Copy link
Copy Markdown
Member

🪭 Claude (einfold)

einfold now finds a SUM of a product whose factors read three or more joined relations. In a ddx gradient step, these are the softmax-weighted sums over attention's saved scores. ddx is an XQL Systems project for automatic differentiation of SQL queries. On spike S31's steps, at 1,024 tokens:

  • attention's output O = softmax(S)·V from the saved scores takes 33 ms with einfold, against DataFusion's 302 ms;
  • dV = Pᵀ·dO takes 33 ms, against 653 ms.

Both run on the dense algorithm. The two take 0.7–0.9 s of einfold's 1.7–2.1 s per attention gradient, and the GPT's dP and attention output have the same shape.

In such a step, the plan joins the saved scores s, the values v, and the saved normalizer z, and sums exp(s − m) / z.z * v.x. Its first factor reads s and z, so no single join in the plan splits the product into two operands, and the detector declined.

Decisions to review

  • Regrouping the joins (regrouped). Inner joins on equalities can be joined in any order and give the same rows. So where the top join doesn't split the product, the detector:

    1. collects the relations under the inner equi-joins, and assigns each to the factor that reads it;
    2. joins a relation neither factor reads into the side it's joined with;
    3. joins each side's relations into one operand, on the equalities between them, and makes the equalities between the sides the fold's keys.

    It declines where both factors read one relation, a relation is joined with both sides or neither, a side's relations aren't joined to each other, or a column's name is in two relations. DataFusion still computes each operand, joins and windows included. The node keeps the original plan as its fallback, as every node does. The alternative was a pipeline whose producer is a table read, in the fused kernel. That needs a table producer, masks taken from missing rows, and batch dimensions, which the fused kernel doesn't have. This change is detection alone, and reaches any such product, not only softmaxes.

  • Float / and % may be computed on an operand's every row (movable). On floats, DataFusion gives inf or NaN for a division by zero, never an error. It still fails on integers, so an integer / stays above the join, as fallible_factors_stay_above_the_join checks. Before this change, a factor such as w / z kept even a two-table product from being found.

  • Operand order. The first factor's relations are the first operand, which matters to the dense algorithm: only its first operand may have missing rows without a domain's default. That suits S31's steps, whose first factor is the masked scores.

How it is tested

  • The property test detect_vs_host draws three-relation products: (l.v / m.v) * r.v with m joined to l, l.v * (r.v + m.v) with m joined to r, and (l.v * m.v) * r.v, where m is the domain table by another name. Look-alikes must decline: m joined to both l and r, or read by both factors. The invariants, over 3,000 cases with NULL and duplicate keys, missing rows, NaN, ±inf and zeros (so that divisions by zero happen):
    • the same rows as DataFusion, bit for bit;
    • the rule fires on each product and never on a look-alike.
  • A hand test, products_over_saved_scores_run_dense, is S31's O step: a window over causal scores, a saved normalizer, and values. It checks dense_folds=1, no host plan, and results within 1e-12 of DataFusion's.

🤖 Generated with Claude Code

https://claude.ai/code/session_01M96xSez6PZwTmfaGh2eJgS

@coderabbitai

coderabbitai Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@alxmrs
alxmrs force-pushed the m3/regrouped-operands branch from ee8eeff to a37f74b Compare October 31, 2026 12:43
@alxmrs
alxmrs deleted the branch m3/fill-default October 31, 2026 12:52
@alxmrs alxmrs closed this Oct 31, 2026
@alxmrs

alxmrs commented Oct 31, 2026

Copy link
Copy Markdown
Member Author

🪭 Claude (einfold)

Closed when its base branch was deleted after #129 merged; continued as #131.

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.

1 participant