Skip to main content

GPU-accelerated DataFrame engine: Python ergonomics + Mojo AOT kernels, cross-vendor (NVIDIA/AMD/Apple).

Project description

๐Ÿš€ MXFrame

GPU-accelerated DataFrames โ€” Python ergonomics, Mojo speed, every GPU.

MXFrame is a DataFrame query engine that pairs a Polars-style Python API with pre-compiled Mojo AOT kernels. The same code runs on NVIDIA, AMD, and Apple Silicon โ€” no CUDA required, no JIT compilation at query time.

TPC-H Python Platform License Visualizer


โœจ Why MXFrame?

pandas Polars cuDF (Rapids) MXFrame
GPU support โŒ โŒ โœ… NVIDIA only โœ… Any GPU
Compiled kernels โŒ โœ… Rust โœ… CUDA โœ… Mojo AOT
Install complexity pip pip CUDA + Rapids stack pixi install
TPC-H competitive โŒ โœ… โœ… โœ…
Cross-vendor โŒ โŒ โŒ โœ… NVIDIA/AMD/Apple

MXFrame is the cuDF architecture without the CUDA lock-in.
The kernels are compiled once to a .so at build time โ€” loaded in ~1 ms at process start, then pure dispatch on every query. No per-query JIT tax.

๐ŸŽฅ See how it works: visualize/mxframe_pipeline.html โ€” interactive step-through of how a Python query becomes a plan tree and dispatches to GPU kernels. Open in any browser, no server needed.

โšก Quick Start


Install (Development)### Install (Development)

โšก Quick Start

# 1. Install pixi (Modular's package manager)
curl -fsSL https://pixi.sh/install.sh | bash

# 2. Clone and set up
git clone https://github.com/abhisheksreesaila/mxframe
cd mxframe
pixi install

# 3. Verify GPU is working
pixi run python3 scripts/_check_gpu.py

Your First Query

import pyarrow as pa
from mxframe import LazyFrame, Scan, col, lit

# Create an Arrow table (or load from Parquet/CSV)
data = pa.table({
    "dept":   pa.array(["eng", "eng", "mkt", "mkt", "eng"]),
    "salary": pa.array([120.0, 95.0, 80.0, 110.0, 130.0], pa.float32()),
    "age":    pa.array([32, 28, 35, 29, 40], pa.int32()),
})

# Build a lazy query plan โ€” nothing executes yet
result = (
    LazyFrame(Scan(data))
    .filter(col("age") > lit(28))
    .groupby("dept")
    .agg(
        col("salary").sum().alias("total_salary"),
        col("salary").mean().alias("avg_salary"),
        col("age").count().alias("headcount"),
    )
    .sort(col("total_salary"), descending=True)
    .compute(device="gpu")   # or "cpu"
)

print(result.to_pandas())

Output:

  dept  total_salary  avg_salary  headcount
0  eng         345.0       115.0          3
1  mkt         110.0       110.0          1

๐Ÿ“Š TPC-H Benchmark โ€” all 22 queries

Hardware: NVIDIA RTX 3090 (sm_86) ยท AMD 12-core CPU ยท Mojo 0.26.2 AOT kernels Baselines: Polars 1.29+ ยท Pandas 3.0 ยท MXFrame CPU path ยท MXFrame GPU path Data: TPC-H schema synthetic data (numpy RNG, fixed seed) Methodology: 1 warmup run + median of 3 timed runs, per engine. Warmup primes every cache an app would have primed on query #2 in production โ€” so these numbers reflect steady-state dispatch, not first-call JIT cost. Source of truth: scripts/bench_results_1M.csv and scripts/bench_results_10M.csv โ€” committed in repo, reproducible via scripts/benchmark_all_22.py

How the kernels dispatch

Device Path Coverage
CPU 100% ctypes into pre-compiled libmxkernels_aot.so All 22 queries โ€” group aggs, masked aggs, inner + left joins, gather, filter, sort, unique
GPU ctypes into pre-compiled libmxkernels_aot_gpu.so All grouped aggs (sum/min/max/count) + masked global aggs
GPU MAX Graph, shape-cached model Hash joins only โ€” compiled once per (n_left, n_right) shape, cached for the session

No per-query JIT on CPU. GPU aggregations skip MAX Graph entirely. GPU joins compile a model once per shape and reuse it โ€” the warmup run primes that cache.

๐Ÿ”ฅ Mojo Kernel Catalogue

Every operator that matters has a hand-written Mojo kernel โ€” there is no NumPy or PyArrow fallback in the hot path. Source lives in kernels/, compiled once to kernels.mojopkg (MAX Graph ops) and libmxkernels_aot.so / libmxkernels_aot_gpu.so (AOT ctypes, zero session overhead).

Interactive explainer: visualize/mxframe_pipeline.html โ€” open in any browser to step through how a Python query becomes a plan tree and dispatches to these kernels.

Grouped aggregation kernels (kernels/)

Kernel What it does
group_sum.mojo Per-group sum โ€” shared-memory privatisation up to 8 192 groups, global-atomic fallback beyond
group_min.mojo Per-group minimum โ€” same shared-mem / atomic-fallback design
group_max.mojo Per-group maximum
group_count.mojo Per-group row count (output is float32 for consistent tensor shapes)
group_composite.mojo Fused multi-key composite ID: out[i] = k0[i]ยทs0 + k1[i]ยทs1 + โ€ฆ in one memory pass

Global (ungrouped) aggregation kernels

Kernel What it does
masked_global_agg.mojo Fused masked reductions: sum, sum(aร—b), min, max โ€” a single GPU pass computes the scalar result using only rows where mask[i]=1. No intermediate filtered-table allocation.

Join kernels

Kernel What it does
join_count.mojo Phase 1 of inner hash join โ€” for each left key, count matching right rows
join_scatter.mojo Phase 2 of inner hash join โ€” emit (left_idx, right_idx) index pairs
join_count_left.mojo Phase 1 of left-outer hash join โ€” count matches, record 1 for unmatched left rows
join_scatter_left.mojo Phase 2 of left-outer hash join โ€” emit pairs; unmatched left rows get right_idx = -1

Sort, gather, and utility kernels

Kernel What it does
sort_indices.mojo Bitonic sort โ€” returns a permutation array; used as post-op for ORDER BY on GPU
unique_mask.mojo Mark out[i]=1 at the first row of each run in a sorted array; used by DISTINCT
filter_gather.mojo Prefix-sum + scatter โ€” compact a column by a boolean mask in two passes

AOT-only kernels (kernels_aot/)

These live in the AOT shared libraries (libmxkernels_aot.so / libmxkernels_aot_gpu.so) and are called via ctypes โ€” no MAX Graph session needed, cold start โ‰ˆ 0 ms.

Function What it does
group_encode_i32_gpu GPU open-addressing hash table: assigns dense int32 group IDs to an integer key column, replacing PyArrow dictionary_encode
masked_global_{min,max}_f32_gpu GPU block-reduction min/max for masked global aggregations (added Phase 1)
gather_{f32,i32,i64}_gpu Coalesced GPU gather โ€” used after join and sort to reorder columns on-device

1 M rows โ€” warm median of 3 runs (as of July 7 2026)

All times in milliseconds ยท lower is better. ๐ŸŸข = faster than Polars baseline; bold = MXFrame wins. Q1โ€“Q7 and Q10 measured July 7 2026; remaining rows measured April 20 2026 โ€” same hardware, same methodology.

Query Description MX CPU MX GPU Polars Pandas CPU vs Polars GPU vs Polars
Q1 Filter + 8 aggregations ๐ŸŸข 11.2 87.2 36.0 109.1 3.2ร— 0.4ร—
Q2 Min-cost supplier ๐ŸŸข 6.6 ๐ŸŸข 15.6 16.3 9.5 2.5ร— 1.0ร—
Q3 3-table join + agg ๐ŸŸข 5.6 ๐ŸŸข 23.3 26.4 20.4 4.7ร— 1.1ร—
Q4 Order priority 15.0 192.5 15.0 29.9 1.0ร— 0.1ร—
Q5 Multi-join + groupby ๐ŸŸข 0.6 ๐ŸŸข 4.6 26.8 21.0 44.7ร— 5.8ร—
Q6 Masked global agg ๐ŸŸข 6.6 11.4 10.6 7.6 1.6ร— 0.9ร—
Q7 Shipping volume ๐ŸŸข 0.7 ๐ŸŸข 10.1 40.1 21.5 57.3ร— 4.0ร—
Q8 Market share ๐ŸŸข 0.9 ๐ŸŸข 4.7 20.2 10.3 22.4ร— 4.3ร—
Q9 Product profit (6-table join) ๐ŸŸข 0.6 ๐ŸŸข 6.6 39.9 17.8 66.5ร— 6.0ร—
Q10 Customer revenue ๐ŸŸข 3.6 ๐ŸŸข 16.5 37.5 22.4 10.4ร— 2.3ร—
Q11 Important stock ๐ŸŸข 0.5 ๐ŸŸข 2.7 7.4 3.0 14.8ร— 2.7ร—
Q12 2-table join + agg ๐ŸŸข 1.0 ๐ŸŸข 4.4 25.0 788.6 25.0ร— 5.7ร—
Q13 Customer distribution ๐ŸŸข 16.2 30.2 27.5 33.5 1.7ร— 0.9ร—
Q14 Promo revenue ๐ŸŸข 3.7 ๐ŸŸข 6.3 8.6 288.6 2.3ร— 1.4ร—
Q15 Top-supplier revenue ๐ŸŸข 1.3 11.8 9.9 6.4 7.6ร— 0.8ร—
Q16 Part/supplier relationships ๐ŸŸข 2.1 ๐ŸŸข 6.3 16.9 6.8 8.0ร— 2.7ร—
Q17 Small-qty order ๐ŸŸข 0.3 ๐ŸŸข 2.7 7.9 4.7 26.3ร— 2.9ร—
Q18 Large-volume customers ๐ŸŸข 4.2 ๐ŸŸข 22.3 33.4 16.8 7.9ร— 1.5ร—
Q19 Discounted revenue ๐ŸŸข 10.9 ๐ŸŸข 11.2 19.6 22.4 1.8ร— 1.8ร—
Q20 Potential part promo ๐ŸŸข 4.3 ๐ŸŸข 5.6 30.0 9.6 7.0ร— 5.4ร—
Q21 Suppliers who kept (EXISTS) ๐ŸŸข 26.0 64.1 31.3 28.6 1.2ร— 0.5ร—
Q22 Global sales opportunity ๐ŸŸข 7.6 ๐ŸŸข 16.5 25.4 56.7 3.3ร— 1.5ร—

1 M summary: MX CPU beats Polars on 21/22 queries (Q4 tied); MX GPU beats Polars on 16/22 queries. Headline CPU wins: Q9 66ร—, Q7 57ร—, Q5 45ร—, Q12 25ร—, Q17 26ร—. Headline GPU wins: Q9 6.0ร—, Q5 5.8ร—, Q12 5.7ร—, Q20 5.4ร—, Q8 4.3ร—.

10 M rows โ€” warm median of 3 runs (as of April 20 2026)

All times in milliseconds ยท lower is better. ๐ŸŸข = faster than Polars baseline; bold = MXFrame wins. At 10M rows the join-heavy queries show the biggest wins โ€” the GPU kernel advantage compounds with data size.

Query Description MX CPU MX GPU Polars Pandas CPU vs Polars GPU vs Polars
Q1 Filter + 8 aggregations ๐ŸŸข 361.0 1190.7 946.5 1771.7 2.6ร— 0.8ร—
Q2 Min-cost supplier ๐ŸŸข 5.7 ๐ŸŸข 11.9 15.4 7.6 2.7ร— 1.3ร—
Q3 3-table join + agg ๐ŸŸข 57.7 ๐ŸŸข 67.2 72.2 581.8 1.3ร— 1.1ร—
Q4 Order priority 301.5 492.2 113.8 807.6 0.4ร— 0.2ร—
Q5 Multi-join + groupby ๐ŸŸข 2.8 ๐ŸŸข 13.8 60.7 332.9 21.7ร— 4.4ร—
Q6 Masked global agg 399.6 523.2 92.0 246.4 0.2ร— 0.2ร—
Q7 Shipping volume ๐ŸŸข 1.8 ๐ŸŸข 16.4 76.4 392.5 42.4ร— 4.7ร—
Q8 Market share ๐ŸŸข 1.3 ๐ŸŸข 3.8 40.9 55.1 31.5ร— 10.8ร—
Q9 Product profit ๐ŸŸข 0.7 ๐ŸŸข 7.4 89.7 431.3 128.1ร— 12.1ร—
Q10 Customer revenue ๐ŸŸข 39.2 ๐ŸŸข 45.0 131.1 216.2 3.3ร— 2.9ร—
Q11 Important stock ๐ŸŸข 0.4 ๐ŸŸข 3.1 6.6 2.5 16.5ร— 2.1ร—
Q12 2-table join + agg ๐ŸŸข 1.3 ๐ŸŸข 4.4 116.4 6853.6 89.5ร— 26.5ร—
Q13 Customer distribution 385.1 396.1 285.8 463.9 0.7ร— 0.7ร—
Q14 Promo revenue ๐ŸŸข 14.4 ๐ŸŸข 16.9 29.7 2719.2 2.1ร— 1.8ร—
Q15 Top-supplier revenue ๐ŸŸข 2.7 57.4 16.1 30.0 6.0ร— 0.3ร—
Q16 Part/supplier relationships ๐ŸŸข 2.7 ๐ŸŸข 6.5 16.3 6.8 6.0ร— 2.5ร—
Q17 Small-qty order ๐ŸŸข 0.6 ๐ŸŸข 1.5 14.6 17.0 24.3ร— 9.7ร—
Q18 Large-volume customers ๐ŸŸข 46.8 69.4 63.4 242.8 1.4ร— 0.9ร—
Q19 Discounted revenue ๐ŸŸข 100.4 ๐ŸŸข 97.9 112.9 234.8 1.1ร— 1.2ร—
Q20 Potential part promo ๐ŸŸข 32.3 ๐ŸŸข 37.1 39.9 52.9 1.2ร— 1.1ร—
Q21 Suppliers who kept 756.0 705.3 85.9 216.6 0.1ร— 0.1ร—
Q22 Global sales opportunity ๐ŸŸข 54.1 ๐ŸŸข 59.2 132.8 1292.1 2.5ร— 2.2ร—

10 M summary: MX CPU beats Polars on 18/22 queries; MX GPU beats Polars on 15/22. ๐ŸŸข Join-heavy queries scale dramatically: Q9 128ร—, Q12 89ร—, Q7 42ร—, Q8 31ร—, Q17 24ร—, Q5 22ร— CPU vs Polars. GPU join wins: Q12 26.5ร—, Q9 12ร—, Q8 10.8ร—, Q17 9.7ร—. At 10M, Q4/Q6/Q13/Q21 show Polars' strength on pure CPU-vectorised operations โ€” these are Phase 6 targets (GPU string encoding + device-resident joins).

Where MXFrame loses (same at both scales)

  • Q4, Q6, Q13, Q21 โ€” operations where our kernel path falls back to PyArrow compute or does extra passes. These are the focus of the next milestone (see roadmap.md).

What the numbers mean

  • Correctness โœ… โ€” all 22 queries return results that round-trip through Pandas and match Polars output.
  • Coverage โœ… โ€” every TPC-H query has a CPU AOT path; all group aggs/masked aggs have GPU AOT paths; GPU joins use shape-cached MAX Graph models.
  • No JIT tax in steady state โ€” after the first query of each shape warms the GPU join model cache, every subsequent call is pure dispatch. The CPU path has no JIT at all.
  • Why GPU doesn't always win โ€” GPU wins scale with workload size and kernel coverage. At 10 M, GPU crushes Polars on the join-heavy queries (Q8/Q9/Q12) where Mojo's shape-cached kernels pay off. Where GPU loses, it's either PCIe overhead on tiny outputs (Q1, Q6) or ops that still route through PyArrow fallback (Q4, Q13, Q21).

โš ๏ธ Current Limitations: Where PyArrow and NumPy Still Run

MXFrame is not 100% Mojo end-to-end โ€” and that is a deliberate, documented trade-off, not a hack. The computational hot path (aggregation, joins, sort, gather) is fully Mojo-compiled. Certain orchestration steps still use PyArrow or NumPy for specific technical reasons explained below.

What still runs in PyArrow / NumPy

Operation Library used Technical reason
String predicate masks โ€” isin, startswith, contains, == on string cols PyArrow compute (SIMD C++) GPU string kernels require UTF-8 variable-length storage. The mask itself is cheap (microseconds at 1M rows); the expensive aggregation or join that follows still runs on GPU.
String group-key encoding โ€” e.g. l_returnflag, n_name PyArrow dictionary_encode Phase 3 added GPU hash-table encoding for integer keys. String hashing on GPU requires a variable-length string type not yet in the kernel set. Result is cached after the first call โ€” zero cost on hot runs.
Table assembly after joins โ€” string and date columns pa.Table.take() Numeric columns (float32, int32) are already gathered on GPU via gather_f32/i32_gpu. String and date columns have no GPU column representation yet, so they are gathered on CPU via Arrow's optimised .take().
Intermediate table materialisation between join and aggregation pa.Table.from_arrays After a join, the result is stored as a CPU Arrow table before the next plan step. Phase 4 removes this round-trip โ€” see Roadmap below.
Window functions โ€” rank, dense_rank, lag, lead, cum_sum NumPy These are not required by any of the 22 TPC-H queries. They exist in the API for completeness; GPU ports are Phase 7+.
DISTINCT pa.Table.group_by().aggregate([]) Always applied as a post-op on an already-aggregated result (typically < 1 000 rows). The cost is negligible; porting it is not a priority.
Plan-level orchestration โ€” predicate push-down, join reorder, filter merge Pure Python This is metadata, not data movement. No rows are touched here.

Why the benchmarks are still honest

The benchmark methodology uses 1 warmup run + median of 3 timed runs. The warmup run primes three caches:

  • _GROUP_ENCODE_CACHE โ€” group-key dictionary encoding result (PyArrow SIMD, runs once per unique (table, keys) pair)
  • _INPUT_PREP_CACHE โ€” column array preparation and filter masking
  • _JOIN_RESULT_CACHE โ€” join output pa.Table (same input tables โ†’ same result)

After warmup, the 3 timed runs do zero PyArrow encoding and zero re-upload of stable column data. They measure pure kernel dispatch + GPU execution โ€” which is the steady-state production cost.

Cold-run numbers (first query after clear_cache()) are higher because encoding and upload happen once. That is a real cost and Phase 4 reduces it for join-heavy queries.


๐Ÿ—บ๏ธ Roadmap: Remaining Mojo Work

The table below lists what remains to make MXFrame fully GPU-native. Items are ordered by performance impact, not difficulty.

Phase What Queries affected Status
Phase 4 Device-resident join pipeline โ€” after gather_f32/i32_gpu produces gathered columns keep them as device buffers; feed directly into group_sum_f32_gpu without pa.Table.from_arrays round-trip Q3, Q5, Q7, Q8, Q9, Q10, Q18, Q21 ๐Ÿ”ฒ Planned
Phase 5 GPU top-k kernel โ€” ORDER BY โ€ฆ LIMIT n via per-block heap; avoids full bitonic sort of large intermediates before the final slice Q3, Q5, Q8, Q9, Q20, Q21 ๐Ÿ”ฒ Planned
Phase 6 GPU string/category encoding โ€” open-addressing hash table for variable-length keys, replaces PyArrow dictionary_encode for string group-by columns Q1, Q4, Q5, Q7, Q8, Q9, Q12 ๐Ÿ”ญ Future
Phase 7 GPU string predicate evaluation โ€” isin, startswith, contains on GPU; eliminates PyArrow boolean mask for string filters Q4, Q12, Q16, Q19 ๐Ÿ”ญ Future
Phase 8 GPU window functions โ€” rank, dense_rank, lag, lead, cum_sum Non-TPC-H workloads ๐Ÿ”ญ Future

Why Phases 4โ€“5 are the highest ROI

Phases 4 and 5 target the cold-run round-trip: the CPU pa.Table that currently sits between a join and its downstream aggregation. On hot runs this round-trip is already eliminated by the join-result cache โ€” so steady-state benchmark numbers are unaffected. On cold runs (fresh process, first query of a new shape), removing pa.Table.from_arrays + re-upload can save 20โ€“80 ms for 1M-row join intermediates.

Phases 6 and 7 target operations that are already SIMD-fast in PyArrow C++ and already cached after the first call. They matter most for workloads that constantly see new table instances (streaming, per-request analytics) where the cache cannot absorb the encoding cost.

Current GPU coverage: python scripts/audit_gpu_paths.py --device gpu --min-gpu-coverage 0.8 exits 0 with 22/22 queries GPU-CLEAN (100%) โ€” every computationally heavy operator reaches a Mojo GPU kernel. The remaining PyArrow code is orchestration and string handling, not the reduction or join bottleneck.


๐Ÿ” Reproducing the Benchmark

To run the benchmark with official TPC-H data (generated by DuckDB's faithful port of the TPC-H dbgen tool):

# Step 1 โ€” generate TPC-H data (requires: pip install duckdb)
#   SF=1  โ†’  ~6M lineitem rows,  ~200 MB Parquet
#   SF=0.1 โ†’ ~600K rows, quick sanity check
pixi run python3 scripts/gen_tpch_parquet.py --sf 1

# Step 2 โ€” run the 22-query benchmark against real data
pixi run python3 scripts/bench_real_tpch.py --data-dir data/tpch_sf1 --runs 3

The generated data/tpch_sf1/ directory contains 8 Parquet files (one per TPC-H table) that you can inspect, share, or version-control.

Scale factor guide

--sf lineitem rows approx size use case
0.01 ~60K 2 MB smoke test / CI
0.1 ~600K 20 MB local dev
1 ~6M 200 MB standard published benchmark
10 ~60M 2 GB stress test

Data lineage & legal note

  • Data is generated by DuckDB's TPC-H extension โ€” a faithful port of the official TPC-H dbgen v3.0.1 with the same value distributions (uniform, Zipfian, pseudo-random vocab).
  • TPC-Hยฎ is a trademark of the Transaction Processing Performance Council. These results are an independent, non-certified benchmark. They may not be reported as "TPC-H results" without formal TPC certification.
  • Reference: https://www.tpc.org/tpch/

๐Ÿ”ค API Reference

LazyFrame

from mxframe import LazyFrame, Scan, col, lit, when

lf = LazyFrame(Scan(arrow_table))
Method Description Example
.filter(expr) Row filter .filter(col("x") > lit(10))
.select(*cols) Column projection .select("a", "b", col("c").alias("d"))
.with_columns(*exprs) Add/replace columns .with_columns((col("a") * lit(2)).alias("a2"))
.groupby(*keys) Start grouped agg .groupby("dept", "region")
.join(other, left_on, right_on, how) Hash join .join(lf2, "id", "fk_id", how="inner")
.sort(expr, descending) Sort rows .sort(col("revenue"), descending=True)
.limit(n) Take first N rows .limit(100)
.distinct() Deduplicate rows .distinct()
.compute(device) Execute the plan .compute(device="gpu")

Expressions (col, lit, when)

# Arithmetic
col("price") * (lit(1.0) - col("discount"))

# Comparison
col("date") >= lit(19940101)

# Boolean combine
(col("x") > lit(0)) & (col("y") < lit(100))

# Conditional
when(col("nation") == lit("BRAZIL"), col("revenue"), lit(0.0))

# String
col("phone").startswith("13")

# Date parts
col("orderdate").year()    # extract year as int32

# Aggregations (inside .agg())
col("salary").sum()
col("salary").mean()
col("salary").min()
col("salary").max()
col("id").count()

SQL Frontend

from mxframe.sql_frontend import sql

result = sql("""
    SELECT dept, SUM(salary) AS total, COUNT(*) AS n
    FROM employees
    WHERE age > 30
    GROUP BY dept
    ORDER BY total DESC
""", employees=arrow_table)

๐Ÿ”ง Supported Operations

Category Operations
Filter >, >=, <, <=, ==, !=, &, |, ~, isin, startswith, contains
Aggregation sum, mean, min, max, count
Groupby Single key, multi-key, composite key
Join Inner, Left outer
Sort Single/multi column, ascending/descending
Window year() date part extraction
Projection select, with_columns, alias, arithmetic expressions
Semi-join Via unique-key inner join
Anti-join Via pc.is_in + pc.invert
Distinct Full row deduplication
SQL SELECT, FROM, WHERE, GROUP BY, ORDER BY, LIMIT, JOIN

๐Ÿ“ Project Structure

mxframe/
โ”œโ”€โ”€ __init__.py            โ† Public API (LazyFrame, Scan, col, lit, when, sql)
โ”œโ”€โ”€ lazy_frame.py          โ† LazyFrame, LazyGroupBy, Scan
โ”œโ”€โ”€ lazy_expr.py           โ† Expr, col(), lit(), when()
โ”œโ”€โ”€ compiler.py            โ† LogicalPlan โ†’ MAX Graph compiler
โ”œโ”€โ”€ custom_ops.py          โ† Dispatch: AOT kernels / MAX Graph / PyArrow fallback
โ”œโ”€โ”€ optimizer.py           โ† Plan rewrites (filter pushdown, join reordering)
โ”œโ”€โ”€ plan_validation.py     โ† Pre-execution plan checks
โ”œโ”€โ”€ sql_frontend.py        โ† SQL โ†’ LogicalPlan via sqlglot
โ”‚
โ”œโ”€โ”€ kernels_aot/           โ† Pre-compiled AOT shared libraries
โ”‚   โ”œโ”€โ”€ libmxkernels_aot.so      โ† CPU kernels (ctypes-callable)
โ”‚   โ””โ”€โ”€ libmxkernels_aot_gpu.so  โ† GPU kernels (CUDA/ROCm/Metal)
โ”‚
โ”œโ”€โ”€ kernels/               โ† Mojo kernel source (build time only)
โ”‚   โ”œโ”€โ”€ group_sum.mojo, group_min.mojo, group_max.mojo ...
โ”‚   โ”œโ”€โ”€ join_scatter.mojo, join_count.mojo
โ”‚   โ”œโ”€โ”€ join_scatter_left.mojo, join_count_left.mojo
โ”‚   โ””โ”€โ”€ filter_gather.mojo, gather_rows.mojo, unique_mask.mojo ...
โ”‚
โ”œโ”€โ”€ kernels_aot/
โ”‚   โ”œโ”€โ”€ kernels_aot.mojo         โ† CPU AOT entry points
โ”‚   โ””โ”€โ”€ kernels_aot_gpu.mojo     โ† GPU AOT entry points
โ”‚
โ”œโ”€โ”€ scripts/
โ”‚   โ”œโ”€โ”€ bench_simple.py          โ† Clean 4-col benchmark (Pandas|Polars|MX CPU|MX GPU)
โ”‚   โ”œโ”€โ”€ benchmark_tpch.py        โ† All 22 TPC-H query implementations
โ”‚   โ”œโ”€โ”€ _test_aot_smoke.py       โ† AOT kernel smoke tests
โ”‚   โ””โ”€โ”€ quickstart.py            โ† Minimal hello-world example
โ”‚
โ””โ”€โ”€ docs/
    โ”œโ”€โ”€ vision-and-architecture.md
    โ”œโ”€โ”€ CONTRIBUTING.md          โ† Developer guide
    โ””โ”€โ”€ PUBLISHING.md            โ† pip release steps

๐Ÿ–ฅ๏ธ Device Selection

# CPU (default, works everywhere)
result = lf.compute(device="cpu")

# GPU (requires NVIDIA/AMD/Apple Silicon with MAX runtime)
result = lf.compute(device="gpu")

The GPU path uses Mojo's DeviceContext โ€” the same source compiles to:

  • PTX on NVIDIA (CUDA-compatible)
  • HSA/ROCm on AMD
  • Metal on Apple Silicon

๐Ÿงช Running Tests

# Smoke tests โ€” AOT kernels
pixi run python3 scripts/_test_aot_smoke.py

# All TPC-H correctness checks
pixi run python3 scripts/_test_phase6_tpch_tier2.py

# GPU check
pixi run python3 scripts/_check_gpu.py

# Full 22-query benchmark
pixi run python3 scripts/bench_simple.py --rows 1000000 --runs 3

๐Ÿ“ฆ Dependencies

Package Required Purpose
pyarrow >= 14 โœ… Column storage, zero-copy NumPy bridge
numpy >= 1.24 โœ… Vectorized pre/post processing
pandas >= 2.0 โœ… Reference implementations, Pandas bridge
modular >= 26.2 GPU only MAX Engine runtime, Mojo GPU dispatch
polars >= 0.20 optional Polars bridge + benchmark comparison
sqlglot >= 25 optional SQL frontend parsing

๐Ÿค Contributing

See CONTRIBUTING.md for the developer guide, kernel writing guidelines, and how to add new TPC-H queries.


๐Ÿ“„ License

Apache 2.0 โ€” see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mxframe-0.2.1.tar.gz (2.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mxframe-0.2.1-py3-none-manylinux_2_34_x86_64.whl (2.1 MB view details)

Uploaded Python 3manylinux: glibc 2.34+ x86-64

File details

Details for the file mxframe-0.2.1.tar.gz.

File metadata

  • Download URL: mxframe-0.2.1.tar.gz
  • Upload date:
  • Size: 2.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mxframe-0.2.1.tar.gz
Algorithm Hash digest
SHA256 256991870a950ef70abaea4a656becda88de5cb82b28c0d0f9bbbd97cdf30b42
MD5 5587a8a52004e06033b8917b3aad523f
BLAKE2b-256 cdcd3a11c10ba83e999e7efb89d15b390429db9f63b2e4bc28e42969ad0085d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for mxframe-0.2.1.tar.gz:

Publisher: publish.yml on abhisheksreesaila/mxframe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mxframe-0.2.1-py3-none-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for mxframe-0.2.1-py3-none-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 b1158b470de02a17995235639b39ebf150f0acf5722799e73c0d7bce5c1a50e4
MD5 a2b1aded17c1a884798fc30d9c27f935
BLAKE2b-256 4a50a84dec947f002533e5aa7a4dc2ce86c3ca79bec8491c9ae455f8c5207b8c

See more details on using hashes here.

Provenance

The following attestation bundles were made for mxframe-0.2.1-py3-none-manylinux_2_34_x86_64.whl:

Publisher: publish.yml on abhisheksreesaila/mxframe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page