Repository navigation
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
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. |
alxmrs
force-pushed
the
graphcast-weights
branch
8 times, most recently
from
October 21, 2026 00:23
b821fa1 to
644ead4
Compare
alxmrs
force-pushed
the
graphcast-weights
branch
from
October 21, 2026 09:17
644ead4 to
4f29d2f
Compare
alxmrs
force-pushed
the
graphcast-weights
branch
2 times, most recently
from
October 25, 2026 03:25
bdce766 to
8f358fd
Compare
alxmrs
added a commit
that referenced
this pull request
Oct 25, 2026
GraphCast takes about 6 minutes at its default 2 rounds and builds on WeatherBench 2 data, so it lands with the work on its published weights (#270). This PR keeps the attention and nanoGPT demos. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
alxmrs
force-pushed
the
graphcast-weights
branch
from
October 25, 2026 16:51
8f358fd to
785c32b
Compare
alxmrs
force-pushed
the
graphcast-weights
branch
from
October 25, 2026 18:44
785c32b to
1721481
Compare
alxmrs
force-pushed
the
graphcast-weights
branch
from
October 25, 2026 19:24
1721481 to
12e33f5
Compare
alxmrs
force-pushed
the
ml-demos
branch
2 times, most recently
from
October 25, 2026 19:25
536b005 to
968b41e
Compare
alxmrs
force-pushed
the
graphcast-weights
branch
3 times, most recently
from
October 25, 2026 20:56
b0fe9af to
e05fae2
Compare
ddxdb 0.3.3 keeps each gradient program between calls (xqlsystems/ddx#164), plans each CTE an objective reads twice on its own (xqlsystems/ddx#168), and differentiates attention's masked product as jax.grad does (xqlsystems/ddx#162). Alternating runs with 0.3.2 on DataFusion: - GPT training step, SGD: 2.8 s -> 1.2 s (first step 2.0 s) - GPT training step, AdamW: 3.2 s -> 1.55 s - attention gradient at 512 tokens: 2.8 s -> 1.1 s (window), 2.7 s -> 1.3 s (GROUP BY) Every check against JAX still passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
ddxdb 0.4.0 exchanges Substrait with datafusion 55.0.0, the version xarray-sql now pins. Its gradients, programs and API are unchanged from 0.3.3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
On DataFusion 55 with ddxdb 0.4.0 and xarray-sql's in-memory tables, the GPT's forward loss takes 3.0 s (9.4 s), an SGD step 0.75 s (1.2 s) and an AdamW step 0.85 s (1.55 s). Attention's forward pass at 512 tokens takes 0.28 s and 0.37 s, and its gradients 0.92 s and 0.93 s. Every result still matches JAX. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
The DuckDB host sends statements that call grad, vjp or jvp to ddxdb.duckdb.sql_all, as xarray-sql's Context does on DataFusion. A gradient ddx or DuckDB's Substrait producer refuses is recorded with the reason (Report.attempt), and a refused training step ends that host's run, since later steps start from its weights. Measured with ddx's development branch (after ddxdb 0.4.1): attention's GROUP BY spelling differentiates on DuckDB and matches jax.grad; the window spelling and the GPT are refused (xqlsystems/ddx#195). The README records the timings and why DuckDB's gradient is slower: its join order over Arrow scans in ddx's two big contractions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
--layers, --embed, --heads and --context set nanoGPT's n_layer, n_embd, n_head and block_size; the defaults are the model as it was. The README records a profile on DataFusion: the loss's time is planning (a reused physical plan runs in 1.8 ms), a second layer multiplies the plan by about 100 and runs out of memory, and JAX's times are the target. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
GraphCast takes about 6 minutes at its default 2 rounds and builds on WeatherBench 2 data, so it lands with the work on its published weights (#270). This PR keeps the attention and nanoGPT demos. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
block() was one long template. It is now the composition nanoGPT's Block is, of CausalSelfAttention and MLP, with the residual connections as their own function. The SQL is the same, but for two table aliases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
tests/test_ml_demos.py runs every demo at its smallest size, each checked against JAX, and a new ml demos CI job installs JAX to run it. benchmarks/ml/CONTRIBUTING.md says what a demo is made of, how to write its SQL, and what to do when ddx or an engine can't run it. The performance work is tracked in #285. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
ddxdb 0.4.2 has the DuckDB backend, ddxdb.duckdb, which the DuckDB host imports; 0.4.1 didn't. The demos' numbers are re-recorded on it. Every check against JAX passes. On DuckDB, a loss may now take a gradient with respect to a table that a view doesn't read. A view whose CTE computes a window and is read twice is still refused (xqlsystems/ddx#204). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
alxmrs
force-pushed
the
graphcast-weights
branch
from
October 26, 2026 02:11
4bcbbbd to
5c39c17
Compare
…uckDB - A demo names the refusals it expects, by host and the start of the error; Report.finish exits with an error for any other, so CI notices a gradient a new ddxdb refuses. - CI runs demo 2 with AdamW too. - tests/test_ad.py: vjp and jvp through Context.sql, against their closed forms; the refusal test reaches a GROUP BY key that depends on w. - jax and ddxdb[duckdb] join the dev group, so the lock pins JAX and puts DuckDB at the 1.5.6 ddxdb declares; CI's ml demos job no longer installs JAX on its own, and the unit test job leaves the demos to it. - Docs: run a ddx checkout with .venv/bin/python, since uv run ignores --no-sync for a script with inline metadata; a demo's dependency goes in the dev group too; the lazy read's cost and the JAX comparison, fixed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
Context.sql sends a query that calls grad, vjp or jvp to ddx, and runs any other through main's path, which forgets a replaced table's Dataset. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
ddxdb 0.4.3 differentiates a view whose CTE computes a window on DuckDB (xqlsystems/ddx#204), so the demos no longer expect DuckDB to refuse attention's window spelling or the GPT's training step. Record the GPT on DuckDB: its weights match JAX's, its loss takes 0.062 s against DataFusion's 2.7 s, and an SGD step takes 0.87 s against 0.41 s, most of it DuckDB planning ddx's 77 steps afresh and the adapter's reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
DataFusion plans a CTE again at every place that reads it, so a model whose CTEs read each other more than once has a plan that grows exponentially with its depth (#267). The 1-layer loss took 2.7 s at the demo's size and 108 s at nanoGPT's CPU size, and the 2-layer loss ran out of memory while planning. - The GPT's SQL builders return their CTEs as (name, sql) pairs, and every statement starts with the model's and the loss's CTEs, through _hosts.with_query. - Hosts gain query_with(ctes, select) and operators_with. DataFusion's runs each CTE on its own into an in-memory table that later CTEs read, under TODO(apache/datafusion#26237). It uses collect_partitioned and register_record_batches rather than DataFrame.cache(), which einfold can't yet plan a join of (xqlsystems/einfold#93). - The model is no longer the view logits. Creating a DataFusion view writes its CTEs out, so the 3-layer view didn't fit in 8 GB; ddx, given the CTEs inline, computes each shared one once. apache/datafusion#24780's streaming fan-out example doesn't fit these queries: by its own notes it can deadlock when both sides of a hash join read the shared plan, and doesn't nest. DataFusion 55 parses `AS MATERIALIZED` only in its PostgreSQL dialect, and ignores it. With ddxdb 0.4.4, at batch 4, on an Intel i7-8700: the 2-layer loss takes 0.07 s on DataFusion, and a 6-layer SGD step 2.4 s, against 0.30 s and 5.5 s on DuckDB; every step matches JAX. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
…reader ddxdb 0.4.5 releases ddx's fixes for attention's backward (xqlsystems/ddx#220, #225), drops intermediate tables once nothing reads them (#223), and halves DuckDB's per-call overhead (#224). The GPT demo's steps match JAX on it, on DataFusion and DuckDB. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
einfold, a query optimizer for DataFusion that runs tensor computations in SQL with array algorithms, released its first candidate. The demos gain an einfold host: xarray-sql's Context with einfold as its query planner. Demo 1 now checks that einfold runs both spellings of attention, and the Nadaraya-Watson control, as one fused pipeline: FlashAttention's tiled plan, found from the SQL. The README gives einfold's numbers. einfold has no Windows wheel yet (xqlsystems/einfold#118), so the dev group skips it on Windows rather than build it from source. ddxdb 0.4.6 differentiates through UNION ALL and computes a step read once inside its reader, which takes the GPT's program from 77 steps to 64. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
Context.sql sent a query to ddx when "grad(" appeared anywhere in its
text, so a parameterized query with the word in a string literal raised
TypeError. calls_ad now ignores string literals and comments.
jaxlib publishes no wheels for Intel macOS, so the dev group installs
JAX everywhere else, and the demos' test skips without it. The demos'
README says what the Nadaraya-Watson estimator is.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
einfold 0.1.0rc2 allocates large blocks with the system's allocator, so fused attention at 32,768 tokens peaks 0.1 GB lower than on rc1 (xqlsystems/einfold#119). The ml demos job installs the test extra too, as review asked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
Each piece of the model took the names of its input and output tables
and returned the CTEs it added, as (name, sql) pairs: a shape the
DataFusion workaround for shared CTEs needed, which made the model hard
to read. Now each piece takes relations and returns one, a SELECT that
reads its inputs by name, so a block reads as nanoGPT's Block.forward:
x = residual(x, attention(layer_norm(x, "ln_1", layer), layer))
return residual(x, mlp(layer_norm(x, "ln_2", layer), layer))
_relation.py lists every relation a loss reads, in order, as the CTEs of
one query, and names each one, never as a table it would hide. The SQL
is the same, CTE for CTE, and the demo matches JAX as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
The model is a view again, built by functions that each return a few of its CTEs as text, and the loss is a query that reads it. The DataFusion host no longer runs each CTE on its own, and _relation.py is gone: the demo shows the SQL a reader would write, and the work to make it fast on DataFusion belongs upstream. ddx computes each CTE once on its own, so training steps are as fast as before; DataFusion's forward loss takes 2.8 s rather than 0.04 s, and a model of more than one layer doesn't plan on DataFusion until it computes a shared CTE once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
Each stage of GraphCast_small is now a view of the stages before it, and the checks and the forecast are plain queries of those views. This drops Host.store and Host.drop, which kept each stage as a table so no engine computed a CTE twice: the demos write the SQL a reader would, and making it fast is the engines' work. The hosts keep their memory limit and spill directory, which change no SQL. Rebased onto ml-demos at 6debe24: einfold is a host, with the memory limit like the others. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
alxmrs
force-pushed
the
graphcast-weights
branch
from
October 31, 2026 02:32
5c39c17 to
48e65a1
Compare
This was referenced Oct 31, 2026
Open
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h
This branch has not been deployed
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.
Stacked on #269. This replaces the miniature
03_graphcast.pywith GraphCast_small as DeepMind publishes it:GraphCast is DeepMind's graph neural network for weather forecasting. Here it's written as SQL views over tables registered through xarray-sql, one view per stage.
Status: work in progress. As stored tables, the encoder and one processor round have run end to end on einfold and match DeepMind's model. As views, it doesn't run past the encoder on any engine yet, for the upstream reasons below.
What's here
_graphcast.py: everything on DeepMind's side.gs://dm_graphcast, cached in~/.cache/xarray-sql/graphcast.weights(net, f, g, w),biases,normsandnets(net, name).deepmind_stages()anddeepmind_forecast()run DeepMind's model in float32.mirror()is a plain JAX transcription of the model, checked against DeepMind's. It can stop after any processor round, so the SQL can be checked one round at a time.03_graphcast.py: the model in SQL.mlp(): a matrix product, bias plus swish (x · sigmoid(x)), a second matrix product and bias, then a layer norm throughOVER (PARTITION BY id)windows.CREATE VIEWof the stages before it.receptive_field()andprogram(..., regional=True)write an exact regional forecast: the same stages, each limited by semi-joins to what the region needs. It hasn't run yet.--sizesis the number of processor rounds. At 16, the forecast is checked against DeepMind's.--memory, in GB), and spill to~/.cache/xarray-sql/spill.Measured
Measured on an Intel i7-8700 with einfold 0.1.0rc2, DataFusion 55.0.0, DuckDB 1.5.6 and ddxdb 0.4.6. Details are in #285 and xqlsystems/einfold#36.
Next
deepmind_forecast().ORDER BYdistanceLIMIT k), and plot its error.🤖 Generated with Claude Code
https://claude.ai/code/session_01NyN7idACeDMh94qrnFMu6h