Skip to content

Tracking: ML in SQL as fast as JAX on CPU #285

Open

Description

@alxmrs

🌀 Claude (xarray-sql ML demos)

This issue coordinates the work to make machine learning in SQL fast. The demos in benchmarks/ml (#269) write models as SQL over xarray-sql's tables, train them with ddx, which differentiates SQL queries, and check every result against JAX, Google's library for differentiable array programs. The goal is to match JAX on CPU with a SQL engine. Anyone can pick up a workstream below. Comment here to claim one, or to post a measurement.

Where we are

Intel i7-8700 (6 cores), DataFusion 55.0.0, DuckDB 1.5.6, ddx at its development branch after ddxdb 0.4.1, measured on 2026-10-24 and 2026-10-25. JAX is compiled with jax.jit.

JAX (CPU) DataFusion DuckDB
attention forward, 512 tokens 0.92 ms 0.28 s (window) / 0.37 s (GROUP BY) 0.48 s / 0.27 s
attention gradient, 512 tokens 2.4 ms 0.94 s 2.4 s (GROUP BY)
GPT loss, 1 layer, batch 4 0.15 ms 3.3 s 0.067 s
GPT SGD step 0.37 ms 0.69 s refused (xqlsystems/ddx#195)
GPT loss, 2 layers can't plan (runs out of 8 GB) 0.12 s

The two demos are slow for different reasons:

Workstreams

  1. Plan each shared CTE once. DataFusion plans a CTE once per reference, so ML queries grow exponentially with depth #267. DataFusion 56 (due Oct/Nov 2026, Release DataFusion 56.0.0 (Oct/Nov 2026) apache/datafusion#24461) adds WITH … AS MATERIALIZED (feat: support WITH ... AS [NOT] MATERIALIZED CTEs apache/datafusion#25580), and feat: decide automatically when to materialize a CTE apache/datafusion#26276 would materialize CTEs automatically. Once 56 is out: enable it in Context, check it with xarray-sql's tables, and train the GPT at 2+ layers. ddx must read the new plan nodes too.
  2. Plan once, run many times. Like jax.jit, which compiles once.
  3. ddx's per-step overhead. program: choose step boundaries by what they save (fewer, larger steps) ddx#186 (fewer, larger steps), rewrite: a cached program still optimizes each shared CTE's placeholder (15% of a cached GPT step) ddx#184, run: run a program's independent steps concurrently ddx#157 (run independent steps concurrently).
  4. The FFI cost per scan. A lazy table costs about 1.5 ms per scan through datafusion-ffi (datafusion-ffi rebuilds the session and task context, with every function, on each scan and execute (~1.5 ms per scan) #273). Small in-memory Datasets avoid it (Register small in-memory Datasets as native in-memory tables #275); large ones still pay it.
  5. DuckDB.
  6. Faster execution: einfold. einfold would run as a DataFusion optimizer rule, reading the dense-grid layout that xarray-sql knows about each table. That contract still needs writing down.
  7. Bigger models. 02_nanogpt.py takes --layers, --embed, --heads and --context. nanoGPT's Shakespeare model is 6, 384, 6 and 256. Every workstream above moves this one.

Good places to start

  • Run the demos on your machine, and post the tables here (see below). Other CPUs and OSes are welcome.
  • Peak memory per host, from a fresh process per measurement.
  • The DuckDB join-order repro in workstream 5.
  • A new model as a demo. See benchmarks/ml/CONTRIBUTING.md. A new demo is also a new benchmark.

How to measure

uv run benchmarks/ml/01_attention.py --sizes 64 256 512 --reps 3 --csv attention.csv
uv run benchmarks/ml/02_nanogpt.py --steps 5 --reps 3 --csv nanogpt.csv

With a post, include:

  • the CPU;
  • python -c "import datafusion, duckdb, ddxdb; print(datafusion.__version__, duckdb.__version__, ddxdb.__version__)";
  • the ddx commit, if you built ddx from a checkout.

To see whether a query's time goes to planning or running, time ctx.sql(q).execution_plan() (planning) against ctx.sql(q).to_arrow_table() (planning and running).

Activity

  1. added
    mlGradients in SQL, the ml extra and its demos
    on Oct 25, 2026
  2. alxmrs commented on Oct 25, 2026

    @alxmrs
    MemberAuthor

    🌀 Claude: The demos, re-recorded on ddxdb 0.4.2 (DataFusion 55.0.0, DuckDB 1.5.5, i7-8700). Every check against JAX passes.

    Step DataFusion DuckDB
    GPT loss, 1 layer, batch 4 3.0 s (13,756 operators) 0.063 s (126)
    GPT SGD step, after the first 0.61–0.66 s refused (xqlsystems/ddx#204)
    GPT AdamW step, after the first 0.73–0.75 s refused (xqlsystems/ddx#204)
    attention gradient, 512 tokens, window 0.84 s refused (xqlsystems/ddx#204)
    attention gradient, 512 tokens, GROUP BY 0.95 s 2.4 s

    These match the numbers from ddx's development branch: 0.4.2 is correctness fixes, not speed. On DuckDB, a gradient with respect to a table that a view doesn't read now works. A view whose CTE computes a window and is read twice (a softmax) is still refused, filed as xqlsystems/ddx#204 with a minimal repro. With ddx#203's prepare (not in 0.4.2), a GPT SGD step drops to 0.53 s (details).

  3. alxmrs commented on Oct 25, 2026

    @alxmrs
    MemberAuthor

    🌀 Claude: Workstream 6 (einfold) now has an issue: xqlsystems/einfold#39. It's xarray-sql's facts (what xarray-sql guarantees about each table it registers, checked on #275) and a DataFusion host with einfold on in _hosts.py, so every demo can report einfold on against off, as einfold's design measures it.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    mlGradients in SQL, the ml extra and its demos

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions