mxframe 0.2.1__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. mxframe-0.3.0/CHANGELOG.md +199 -0
  2. mxframe-0.3.0/PKG-INFO +152 -0
  3. mxframe-0.3.0/README.md +119 -0
  4. {mxframe-0.2.1 → mxframe-0.3.0}/__init__.py +1 -1
  5. {mxframe-0.2.1 → mxframe-0.3.0}/aot_kernels.py +193 -0
  6. {mxframe-0.2.1 → mxframe-0.3.0}/custom_ops.py +134 -79
  7. {mxframe-0.2.1 → mxframe-0.3.0}/docs/vision-and-architecture.md +17 -40
  8. mxframe-0.3.0/kernels.mojopkg +0 -0
  9. mxframe-0.3.0/kernels_aot/libmxkernels_aot.so +0 -0
  10. mxframe-0.3.0/kernels_aot/libmxkernels_aot_gpu.so +0 -0
  11. mxframe-0.3.0/mxframe.egg-info/PKG-INFO +152 -0
  12. {mxframe-0.2.1 → mxframe-0.3.0}/mxframe.egg-info/requires.txt +1 -1
  13. {mxframe-0.2.1 → mxframe-0.3.0}/pyproject.toml +2 -2
  14. mxframe-0.2.1/CHANGELOG.md +0 -64
  15. mxframe-0.2.1/PKG-INFO +0 -565
  16. mxframe-0.2.1/README.md +0 -532
  17. mxframe-0.2.1/kernels.mojopkg +0 -0
  18. mxframe-0.2.1/kernels_aot/libmxkernels_aot.so +0 -0
  19. mxframe-0.2.1/kernels_aot/libmxkernels_aot_gpu.so +0 -0
  20. mxframe-0.2.1/mxframe.egg-info/PKG-INFO +0 -565
  21. {mxframe-0.2.1 → mxframe-0.3.0}/MANIFEST.in +0 -0
  22. {mxframe-0.2.1 → mxframe-0.3.0}/_modidx.py +0 -0
  23. {mxframe-0.2.1 → mxframe-0.3.0}/compiler.py +0 -0
  24. {mxframe-0.2.1 → mxframe-0.3.0}/kernels_aot/__init__.py +0 -0
  25. {mxframe-0.2.1 → mxframe-0.3.0}/lazy_expr.py +0 -0
  26. {mxframe-0.2.1 → mxframe-0.3.0}/lazy_frame.py +0 -0
  27. {mxframe-0.2.1 → mxframe-0.3.0}/mxframe.egg-info/SOURCES.txt +0 -0
  28. {mxframe-0.2.1 → mxframe-0.3.0}/mxframe.egg-info/dependency_links.txt +0 -0
  29. {mxframe-0.2.1 → mxframe-0.3.0}/mxframe.egg-info/top_level.txt +0 -0
  30. {mxframe-0.2.1 → mxframe-0.3.0}/optimizer.py +0 -0
  31. {mxframe-0.2.1 → mxframe-0.3.0}/plan_validation.py +0 -0
  32. {mxframe-0.2.1 → mxframe-0.3.0}/setup.cfg +0 -0
  33. {mxframe-0.2.1 → mxframe-0.3.0}/setup.py +0 -0
  34. {mxframe-0.2.1 → mxframe-0.3.0}/sql_frontend.py +0 -0
@@ -0,0 +1,199 @@
1
+ # 📋 Changelog
2
+
3
+ All notable changes to MXFrame are documented here.
4
+ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5
+
6
+ ---
7
+
8
+ ## [0.3.0] — 2026-07-10
9
+
10
+ ### 📚 Docs & Benchmarks
11
+ - README restructured: 543 lines → 119 lines. Intro, quick start, and 4-row teaser only — all detail moved to dedicated docs.
12
+ - New `docs/benchmarks.md`: full 22-query TPC-H tables (1 M + 10 M rows), Mojo kernel catalogue, current limitations, roadmap, and reproduce instructions.
13
+ - New `docs/api.md`: LazyFrame method reference, expression syntax, SQL frontend, supported operations, project structure.
14
+ - `docs/vision-and-architecture.md`: fixed garbled sections 2.5/2.6/3; success criteria table repaired; all milestones marked ✅.
15
+ - `docs/archive/` added to `.gitignore` — old dev notes moved there, not published.
16
+ - All stale `Mojo 0.26.2` / `MAX Graph shape-cached join` references updated to reflect v0.2.3 reality (Mojo 26.4, AOT ctypes everywhere).
17
+
18
+ ### 📊 Benchmark updates
19
+ - Q5/Q7/Q8/Q10/Q13/Q19 re-measured with per-run join-cache clearing (fresh-join). Previous v0.2.0 numbers for those queries were warm join-cache hits.
20
+ - Summary corrected: CPU 20/22 (Q13 loses fresh-join), GPU 12/22 (Q5/Q7 no longer win at 1 M without cache warmup).
21
+ - Q8 GPU marked `—` (MAX Graph `year()` groupby JIT too slow to benchmark; Phase 6 target).
22
+
23
+ ### 🔨 Infrastructure
24
+ - `modular >= 26.4` requirement added to `pyproject.toml` runtime deps and Dependencies table in README.
25
+ - `docs/archive/` gitignored; previously committed archive files removed from history.
26
+
27
+ ---
28
+
29
+ ## [0.2.3] — 2026-07-09
30
+
31
+ ### ⚡ Performance
32
+ - **Phase 4 — Device-resident GPU join pipeline** (`join_count_i32_gpu` + `join_scatter_i32_gpu`):
33
+ GPU inner joins now bypass MAX Graph JIT entirely. Cold-start join latency drops from ~300 ms (MAX session init + JIT) to ~70 ms. `AOTKernelsGPU.hash_join()` caches key arrays via `_cached_upload`; `AOTKernelsGPU.gather_table()` gathers all numeric columns with a single shared device-resident index upload.
34
+ - **Phase 5 — GPU sort + top-k** (`sort_topk_i32_gpu`): `ORDER BY … LIMIT k` fuses sort and limit in a single AOT bitonic sort kernel, downloading only `k × 4` bytes instead of `N × 4`. `_apply_post_ops_custom` peek-ahead passes `topk=k` directly to the sort kernel.
35
+ - **Phase 3 — Vectorised rank mapping**: `_encode_sort_key` replaces the per-unique-value Python `for` loop with a single vectorised NumPy scatter (`rank_of[sorted_order] = np.arange(n_unique)`). ~1.5× speedup for sort-key encoding at 5 M rows.
36
+
37
+ ### 🛠 Fixed
38
+ - **GPU sort+limit crash**: `_apply_sort_custom` was calling `_gpu_gather_table` which referenced `gather_f32` as a MAX Graph custom op — that kernel was never registered in the mojopkg. Any `ORDER BY` on `device="gpu"` would crash. Now routes through `_aot_gpu.gather_table` (AOT ctypes, no MAX Graph).
39
+ - `_apply_sort_custom` CPU path now uses `np.argpartition` (O(N) partial sort) when `topk < N`, instead of a full O(N log N) argsort.
40
+
41
+ ### 🔨 Infrastructure
42
+ - **Mojo/MAX 26.4 migration**: all `kernels/*.mojo` and `kernels_aot/*.mojo` migrated from 26.2 API (`fn` → `def`, `from tensor import` → `from extensibility import`, `DeviceContextPtr` → `DeviceContext`, `enqueue_function_experimental` → `enqueue_function`).
43
+ - **`kernels/_atomic.mojo`** (new): drop-in replacement for the missing `std.os.atomic.Atomic`. Implements `fetch_add`, `min`, `max`, `compare_exchange` via MLIR `llvm.atomicrmw` / `llvm.cmpxchg` instructions — portable across NVIDIA and AMD; works in both `mojo package` (JIT) and `mojo build --emit shared-lib` (AOT) contexts.
44
+ - All compiled artifacts rebuilt with Mojo 1.0.0b2 (modular 26.4): `kernels.mojopkg`, `libmxkernels_aot.so`, `libmxkernels_aot_gpu.so`.
45
+
46
+ ---
47
+
48
+ ## [0.2.2] — 2026-07-08
49
+
50
+ ### 🔨 Infrastructure
51
+ - First release targeting **Mojo/MAX 26.4** (`modular = "26.4.*"` in `pixi.toml`).
52
+ - `_atomic.mojo` shim introduced to replace the removed `std.os.atomic` module.
53
+ - All kernel source files migrated to 26.4 syntax; compiled artefacts rebuilt.
54
+ - `pyproject.toml` `runtime` extra pinned to `modular>=26.4` to prevent 26.2 wheels from being installed by Colab/pip users.
55
+
56
+ ---
57
+
58
+ ## [0.2.1] — 2026-06-xx
59
+
60
+ ### 🔨 Infrastructure
61
+ - TestPyPI re-upload to validate wheel packaging. No functional changes.
62
+
63
+ ---
64
+
65
+ ## [0.2.0] — 2026-05-xx
66
+
67
+ ### ✨ Added
68
+ - **Phase 1 — GPU buffer cache + masked global min/max**:
69
+ - `masked_global_min_f32_gpu` / `masked_global_max_f32_gpu` Mojo AOT kernels.
70
+ - `AOTKernelsGPU` device-buffer cache (`_cached_upload`, eviction, `clear_buf_cache`) — eliminates redundant PCIe uploads on repeated hot queries.
71
+ - `group_mean_f32` GPU kernel (sum + count on GPU, divide on CPU).
72
+ - Masked global min/max fast-paths wired in `custom_ops.py`.
73
+ - **Phase 2 — Masked global aggregation for any expression**:
74
+ - `_compute_masked_global_agg` extended to handle any inner expression via `_eval_expr_arrow` (e.g. `a*(1-b)`, `case_when`, `startswith`, `isin`) — SUM reduction stays GPU-resident.
75
+ - Join-only plans emit `"join_mojo_shortcut"` provenance (not `"pyarrow_shortcut"`) — Q19 restructured to single-pass join+filter+global_agg.
76
+ - `audit_gpu_paths.py` updated: `join_mojo_shortcut` counted as Mojo-backed.
77
+ - **Phase 3 — GPU integer key encoding**:
78
+ - `group_encode_i32_gpu` open-addressing hash-table kernel for integer group keys; replaces PyArrow `dictionary_encode` for integer-keyed group-by on GPU.
79
+ - **Audit tool** (`scripts/audit_gpu_paths.py`): classifies each of 22 TPC-H queries as `GPU-CLEAN` / `MOJO-CPU` / `FALLBACK` via `last_compile_provenance["path"]`.
80
+ - **Interactive visualiser** (`visualize/mxframe_pipeline.html`): step-through of how a Python query becomes a plan tree and dispatches to GPU kernels.
81
+
82
+ ### ⚡ Performance
83
+ - **22/22 TPC-H queries GPU-CLEAN** (100% Mojo-backed on GPU, zero PyArrow fallbacks in the reduction and join hot paths).
84
+
85
+ ---
86
+
87
+ ## [0.1.2] — 2026-04-22
88
+
89
+ ### 🛠 Fixed
90
+ - `pip install "mxframe[runtime]"` now gives a working install. The `[runtime]` extra pulls `modular>=25.5`, which provides the `max.engine` / `max.driver` modules that `mxframe.compiler` imports at module load. (Pixi users get `modular` from the Modular conda channel and should install `mxframe` without the extra.)
91
+ - `sqlglot` import in `mxframe.sql_frontend` is now lazy: `import mxframe` no longer requires the `[sql]` extra. Calling `mxframe.sql(…)` without `sqlglot` installed raises a clear `ImportError` with the install hint.
92
+ - `__init__.py` `__version__` now matches `pyproject.toml`.
93
+
94
+ ---
95
+
96
+ ## [0.1.1] — 2026-04-22
97
+
98
+ ### 🛠 Fixed
99
+ - Packaging: `readme` now points to `README.md` so PyPI shows the full project page with benchmarks and quickstart (was accidentally showing the internal vision/architecture doc)
100
+ - CI: `AOTKernelsGPU` init no longer hard-fails on CPU-only runners (`CUDA driver unavailable` is caught, `self._aot_gpu` falls back to `None`)
101
+ - CI: `_find_kernels_path()` uses `Path(__file__).resolve().parent` directly, removing the stale `/home/ablearn/mxdf/…` dev fallback that surfaced in installed wheels
102
+ - Bug: `NameError: cache_key_count` in `_hash_join_mojo_cpu` MAX Graph fallback
103
+ - Tests: `scripts/_test_phase0_custom_ops.py` and `_test_phase1.py` no longer hard-code a developer's kernels path; they use the auto-detected default
104
+
105
+ ---
106
+
107
+ ## [0.1.0] — 2026-04-20
108
+
109
+ ### ✨ Added
110
+ - **All 22 TPC-H queries** on CPU and GPU AOT paths
111
+ - **GPU LEFT JOIN** — `join_count_left` + `join_scatter_left` Mojo kernels wired to Python (Q13)
112
+ - `bench_simple.py` — clean 4-column benchmark (Pandas | Polars | MX CPU | MX GPU)
113
+ - `--queries` and `--runs` flags for targeted benchmarking
114
+
115
+ ### ⚡ Performance
116
+ - **Q22** phone prefix anti-join: vectorized via `pc.utf8_slice_codeunits` + `pc.is_in` + `np.isin` — 3.6× faster than Polars CPU (was 10× **slower**)
117
+ - **Q20** semi-join chain: eliminated `.to_pandas()` Pandas detour — 8.7× faster than Polars (was comparable)
118
+ - **Q21** EXISTS+NOT EXISTS: replaced `.to_pandas().groupby.nunique()` with NumPy composite key dedup
119
+ - **Q18** large volume customers: replaced `.to_pylist()` semi-join with Mojo join — semi-join now uses AOT kernel path
120
+ - **Q15** argmax supplier: replaced `0.9999 * max_rev` tolerance hack with exact `pc.equal()` on float32
121
+ - **Q13** LEFT JOIN: removed `.to_pandas()` groupby detour — now fully on GPU AOT path (19ms CPU, 29ms GPU vs 25ms Polars)
122
+
123
+ ### 🐛 Fixed
124
+ - `not use_gpu_filter` gate bug in `custom_ops.py` section 4.6 that blocked GPU filter path
125
+ - Q7 nation pre-join cache key now uses `id()` preventing cache misses on repeated hot calls
126
+
127
+ ### 🏗️ Infrastructure
128
+ - `pyproject.toml` updated with full metadata, dependencies, optional extras, package-data for `.so` files
129
+ - `CONTRIBUTING.md` — developer guide with kernel writing tutorial
130
+ - `PUBLISHING.md` — step-by-step pip release guide
131
+ - GitHub Actions: `test.yml` (CI), `publish.yml` (PyPI via OIDC)
132
+
133
+ ### 📊 Benchmark Summary (1M and 10M rows, all 22 queries, warm median of 3)
134
+
135
+ See the full table in [README.md § TPC-H Benchmark](README.md#-tpc-h-benchmark--all-22-queries),
136
+ sourced from `scripts/bench_results_1M.csv` and `scripts/bench_results_10M.csv`.
137
+
138
+ - **Correctness:** 22/22 queries pass on CPU and GPU paths
139
+ - **MX CPU wins vs Polars:** **21/22** at 1 M, **18/22** at 10 M
140
+ — headline: **Q9 128× · Q12 89× · Q7 42× · Q8 31× · Q17 24× · Q5 22×** (at 10 M)
141
+ - **MX GPU wins vs Polars:** **16/22** at 1 M, **15/22** at 10 M
142
+ — headline: **Q12 26.5× · Q9 12× · Q8 10.8× · Q17 9.7× · Q7 4.7×** (at 10 M)
143
+ - **Remaining losses (Q4, Q6, Q13, Q21):** ops that still route through PyArrow fallback — kernel replacements tracked in `roadmap.md`
144
+
145
+ ### 🛠 Fixed
146
+ - `pip install "mxframe[runtime]"` now gives a working install. The `[runtime]` extra pulls `modular>=25.5`, which provides the `max.engine` / `max.driver` modules that `mxframe.compiler` imports at module load. (Pixi users get `modular` from the Modular conda channel and should install `mxframe` without the extra.)
147
+ - `sqlglot` import in `mxframe.sql_frontend` is now lazy: `import mxframe` no longer requires the `[sql]` extra. Calling `mxframe.sql(…)` without `sqlglot` installed raises a clear `ImportError` with the install hint.
148
+ - `__init__.py` `__version__` now matches `pyproject.toml`.
149
+
150
+ ---
151
+
152
+ ## [0.1.1] — 2026-04-22
153
+
154
+ ### 🛠 Fixed
155
+ - Packaging: `readme` now points to `README.md` so PyPI shows the full project page with benchmarks and quickstart (was accidentally showing the internal vision/architecture doc)
156
+ - CI: `AOTKernelsGPU` init no longer hard-fails on CPU-only runners (`CUDA driver unavailable` is caught, `self._aot_gpu` falls back to `None`)
157
+ - CI: `_find_kernels_path()` uses `Path(__file__).resolve().parent` directly, removing the stale `/home/ablearn/mxdf/…` dev fallback that surfaced in installed wheels
158
+ - Bug: `NameError: cache_key_count` in `_hash_join_mojo_cpu` MAX Graph fallback
159
+ - Tests: `scripts/_test_phase0_custom_ops.py` and `_test_phase1.py` no longer hard-code a developer's kernels path; they use the auto-detected default
160
+
161
+ ---
162
+
163
+ ## [0.1.0] — 2026-04-20
164
+
165
+ ### ✨ Added
166
+ - **All 22 TPC-H queries** on CPU and GPU AOT paths
167
+ - **GPU LEFT JOIN** — `join_count_left` + `join_scatter_left` Mojo kernels wired to Python (Q13)
168
+ - `bench_simple.py` — clean 4-column benchmark (Pandas | Polars | MX CPU | MX GPU)
169
+ - `--queries` and `--runs` flags for targeted benchmarking
170
+
171
+ ### ⚡ Performance
172
+ - **Q22** phone prefix anti-join: vectorized via `pc.utf8_slice_codeunits` + `pc.is_in` + `np.isin` — 3.6× faster than Polars CPU (was 10× **slower**)
173
+ - **Q20** semi-join chain: eliminated `.to_pandas()` Pandas detour — 8.7× faster than Polars (was comparable)
174
+ - **Q21** EXISTS+NOT EXISTS: replaced `.to_pandas().groupby.nunique()` with NumPy composite key dedup
175
+ - **Q18** large volume customers: replaced `.to_pylist()` semi-join with Mojo join — semi-join now uses AOT kernel path
176
+ - **Q15** argmax supplier: replaced `0.9999 * max_rev` tolerance hack with exact `pc.equal()` on float32
177
+ - **Q13** LEFT JOIN: removed `.to_pandas()` groupby detour — now fully on GPU AOT path (19ms CPU, 29ms GPU vs 25ms Polars)
178
+
179
+ ### 🐛 Fixed
180
+ - `not use_gpu_filter` gate bug in `custom_ops.py` section 4.6 that blocked GPU filter path
181
+ - Q7 nation pre-join cache key now uses `id()` preventing cache misses on repeated hot calls
182
+
183
+ ### 🏗️ Infrastructure
184
+ - `pyproject.toml` updated with full metadata, dependencies, optional extras, package-data for `.so` files
185
+ - `CONTRIBUTING.md` — developer guide with kernel writing tutorial
186
+ - `PUBLISHING.md` — step-by-step pip release guide
187
+ - GitHub Actions: `test.yml` (CI), `publish.yml` (PyPI via OIDC)
188
+
189
+ ### 📊 Benchmark Summary (1M and 10M rows, all 22 queries, warm median of 3)
190
+
191
+ See the full table in [README.md § TPC-H Benchmark](README.md#-tpc-h-benchmark--all-22-queries),
192
+ sourced from `scripts/bench_results_1M.csv` and `scripts/bench_results_10M.csv`.
193
+
194
+ - **Correctness:** 22/22 queries pass on CPU and GPU paths
195
+ - **MX CPU wins vs Polars:** **21/22** at 1 M, **18/22** at 10 M
196
+ — headline: **Q9 128× · Q12 89× · Q7 42× · Q8 31× · Q17 24× · Q5 22×** (at 10 M)
197
+ - **MX GPU wins vs Polars:** **16/22** at 1 M, **15/22** at 10 M
198
+ — headline: **Q12 26.5× · Q9 12× · Q8 10.8× · Q17 9.7× · Q7 4.7×** (at 10 M)
199
+ - **Remaining losses (Q4, Q6, Q13, Q21):** ops that still route through PyArrow fallback — kernel replacements tracked in `roadmap.md`
mxframe-0.3.0/PKG-INFO ADDED
@@ -0,0 +1,152 @@
1
+ Metadata-Version: 2.4
2
+ Name: mxframe
3
+ Version: 0.3.0
4
+ Summary: GPU-accelerated DataFrame engine: Python ergonomics + Mojo AOT kernels, cross-vendor (NVIDIA/AMD/Apple).
5
+ Author-email: Abhishek Sreesaila <abhisheksreesaila@users.noreply.github.com>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/abhisheksreesaila/mxframe
8
+ Project-URL: Repository, https://github.com/abhisheksreesaila/mxframe
9
+ Keywords: dataframe,gpu,mojo,arrow,analytics,tpch
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
16
+ Classifier: Topic :: Database
17
+ Requires-Python: >=3.12
18
+ Description-Content-Type: text/markdown
19
+ Requires-Dist: pyarrow>=14.0
20
+ Requires-Dist: numpy>=1.24
21
+ Requires-Dist: pandas>=2.0
22
+ Provides-Extra: runtime
23
+ Requires-Dist: modular>=26.4; extra == "runtime"
24
+ Provides-Extra: polars
25
+ Requires-Dist: polars>=0.20; extra == "polars"
26
+ Provides-Extra: sql
27
+ Requires-Dist: sqlglot>=25.0; extra == "sql"
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=7.0; extra == "dev"
30
+ Requires-Dist: polars>=0.20; extra == "dev"
31
+ Requires-Dist: sqlglot>=25.0; extra == "dev"
32
+ Requires-Dist: duckdb>=0.9; extra == "dev"
33
+
34
+ # 🚀 MXFrame
35
+
36
+ > **GPU-accelerated DataFrames — Python ergonomics, Mojo speed, every GPU.**
37
+
38
+ MXFrame is a DataFrame query engine that pairs a Polars-style Python API with
39
+ pre-compiled Mojo AOT kernels. The same code runs on **NVIDIA, AMD, and Apple Silicon** —
40
+ no CUDA required, no JIT compilation at query time.
41
+
42
+ [![TPC-H](https://img.shields.io/badge/TPC--H-22%2F22%20queries-brightgreen)](docs/benchmarks.md)
43
+ [![Python](https://img.shields.io/badge/python-3.12%2B-blue)](pyproject.toml)
44
+ [![Platform](https://img.shields.io/badge/platform-linux--x86__64-lightgrey)](pyproject.toml)
45
+ [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE)
46
+
47
+ ---
48
+
49
+ ## ✨ Why MXFrame?
50
+
51
+ | | pandas | Polars | cuDF (Rapids) | **MXFrame** |
52
+ |---|---|---|---|---|
53
+ | GPU support | ❌ | ❌ | ✅ NVIDIA only | ✅ **Any GPU** |
54
+ | Compiled kernels | ❌ | ✅ Rust | ✅ CUDA | ✅ **Mojo AOT** |
55
+ | Install complexity | pip | pip | CUDA + Rapids stack | **pixi install** |
56
+ | TPC-H competitive | ❌ | ✅ | ✅ | ✅ |
57
+ | Cross-vendor | ❌ | ❌ | ❌ | ✅ NVIDIA/AMD/Apple |
58
+
59
+ MXFrame is the **cuDF architecture without the CUDA lock-in**.
60
+ Kernels are compiled **once** to a `.so` at build time — loaded in ~1 ms, then pure dispatch on every query.
61
+
62
+ ---
63
+
64
+ ## ⚡ Quick Start
65
+
66
+ ```sh
67
+ # 1. Install pixi (Modular's package manager)
68
+ curl -fsSL https://pixi.sh/install.sh | bash
69
+
70
+ # 2. Clone and set up
71
+ git clone https://github.com/abhisheksreesaila/mxframe
72
+ cd mxframe
73
+ pixi install
74
+
75
+ # 3. Verify GPU is working
76
+ pixi run python3 scripts/_check_gpu.py
77
+ ```
78
+
79
+ ```python
80
+ import pyarrow as pa
81
+ from mxframe import LazyFrame, Scan, col, lit
82
+
83
+ data = pa.table({
84
+ "dept": pa.array(["eng", "eng", "mkt", "mkt", "eng"]),
85
+ "salary": pa.array([120.0, 95.0, 80.0, 110.0, 130.0], pa.float32()),
86
+ "age": pa.array([32, 28, 35, 29, 40], pa.int32()),
87
+ })
88
+
89
+ result = (
90
+ LazyFrame(Scan(data))
91
+ .filter(col("age") > lit(28))
92
+ .groupby("dept")
93
+ .agg(
94
+ col("salary").sum().alias("total_salary"),
95
+ col("age").count().alias("headcount"),
96
+ )
97
+ .sort(col("total_salary"), descending=True)
98
+ .compute(device="gpu") # or "cpu"
99
+ )
100
+ print(result.to_pandas())
101
+ ```
102
+
103
+ ```
104
+ dept total_salary headcount
105
+ 0 eng 345.0 3
106
+ 1 mkt 110.0 1
107
+ ```
108
+
109
+ ---
110
+
111
+ ## 📊 Performance — TPC-H at 1 M rows *(v0.3.0)*
112
+
113
+ MX CPU beats Polars on **20/22** queries. GPU advantage compounds at 10 M+ rows where kernel parallelism dominates PCIe upload cost.
114
+
115
+ | Query | MX CPU | MX GPU | Polars | CPU vs Polars |
116
+ |---|---:|---:|---:|---:|
117
+ | Q9 · Product profit (6-table join) | **0.6 ms** | 6.6 ms | 39.9 ms | **67×** |
118
+ | Q12 · 2-table join + agg | **0.5 ms** | 3.4 ms | 23.2 ms | **46×** |
119
+ | Q3 · 3-table join + agg | **2.6 ms** | 8.7 ms | 23.3 ms | **9×** |
120
+ | Q1 · Filter + 8 aggregations | **10.7 ms** | 42.1 ms | 33.3 ms | **3.1×** |
121
+
122
+ → [Full 22-query tables (1 M + 10 M rows), methodology, and reproduce instructions](docs/benchmarks.md)
123
+
124
+ ---
125
+
126
+ ## 📚 Docs
127
+
128
+ | | |
129
+ |---|---|
130
+ | [**API Reference**](docs/api.md) | LazyFrame, expressions, SQL frontend, supported operations, running tests |
131
+ | [**Benchmarks**](docs/benchmarks.md) | Full TPC-H tables, kernel catalogue, limitations, roadmap, reproduce instructions |
132
+ | [**Architecture**](docs/vision-and-architecture.md) | Design philosophy, internal layers, how MAX Graph fits in |
133
+ | [**Contributing**](CONTRIBUTING.md) | Dev setup, writing Mojo kernels, adding queries |
134
+
135
+ ---
136
+
137
+ ## 📦 Dependencies
138
+
139
+ | Package | Required | Purpose |
140
+ |---|---|---|
141
+ | `pyarrow >= 14` | ✅ | Column storage, zero-copy NumPy bridge |
142
+ | `numpy >= 1.24` | ✅ | Vectorized pre/post processing |
143
+ | `pandas >= 2.0` | ✅ | Reference implementations |
144
+ | `modular >= 26.4` | GPU only | MAX Engine runtime, Mojo GPU dispatch |
145
+ | `polars >= 0.20` | optional | Benchmark comparison |
146
+ | `sqlglot >= 25` | optional | SQL frontend parsing |
147
+
148
+ ---
149
+
150
+ ## 📄 License
151
+
152
+ Apache 2.0 — see [LICENSE](LICENSE).
@@ -0,0 +1,119 @@
1
+ # 🚀 MXFrame
2
+
3
+ > **GPU-accelerated DataFrames — Python ergonomics, Mojo speed, every GPU.**
4
+
5
+ MXFrame is a DataFrame query engine that pairs a Polars-style Python API with
6
+ pre-compiled Mojo AOT kernels. The same code runs on **NVIDIA, AMD, and Apple Silicon** —
7
+ no CUDA required, no JIT compilation at query time.
8
+
9
+ [![TPC-H](https://img.shields.io/badge/TPC--H-22%2F22%20queries-brightgreen)](docs/benchmarks.md)
10
+ [![Python](https://img.shields.io/badge/python-3.12%2B-blue)](pyproject.toml)
11
+ [![Platform](https://img.shields.io/badge/platform-linux--x86__64-lightgrey)](pyproject.toml)
12
+ [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE)
13
+
14
+ ---
15
+
16
+ ## ✨ Why MXFrame?
17
+
18
+ | | pandas | Polars | cuDF (Rapids) | **MXFrame** |
19
+ |---|---|---|---|---|
20
+ | GPU support | ❌ | ❌ | ✅ NVIDIA only | ✅ **Any GPU** |
21
+ | Compiled kernels | ❌ | ✅ Rust | ✅ CUDA | ✅ **Mojo AOT** |
22
+ | Install complexity | pip | pip | CUDA + Rapids stack | **pixi install** |
23
+ | TPC-H competitive | ❌ | ✅ | ✅ | ✅ |
24
+ | Cross-vendor | ❌ | ❌ | ❌ | ✅ NVIDIA/AMD/Apple |
25
+
26
+ MXFrame is the **cuDF architecture without the CUDA lock-in**.
27
+ Kernels are compiled **once** to a `.so` at build time — loaded in ~1 ms, then pure dispatch on every query.
28
+
29
+ ---
30
+
31
+ ## ⚡ Quick Start
32
+
33
+ ```sh
34
+ # 1. Install pixi (Modular's package manager)
35
+ curl -fsSL https://pixi.sh/install.sh | bash
36
+
37
+ # 2. Clone and set up
38
+ git clone https://github.com/abhisheksreesaila/mxframe
39
+ cd mxframe
40
+ pixi install
41
+
42
+ # 3. Verify GPU is working
43
+ pixi run python3 scripts/_check_gpu.py
44
+ ```
45
+
46
+ ```python
47
+ import pyarrow as pa
48
+ from mxframe import LazyFrame, Scan, col, lit
49
+
50
+ data = pa.table({
51
+ "dept": pa.array(["eng", "eng", "mkt", "mkt", "eng"]),
52
+ "salary": pa.array([120.0, 95.0, 80.0, 110.0, 130.0], pa.float32()),
53
+ "age": pa.array([32, 28, 35, 29, 40], pa.int32()),
54
+ })
55
+
56
+ result = (
57
+ LazyFrame(Scan(data))
58
+ .filter(col("age") > lit(28))
59
+ .groupby("dept")
60
+ .agg(
61
+ col("salary").sum().alias("total_salary"),
62
+ col("age").count().alias("headcount"),
63
+ )
64
+ .sort(col("total_salary"), descending=True)
65
+ .compute(device="gpu") # or "cpu"
66
+ )
67
+ print(result.to_pandas())
68
+ ```
69
+
70
+ ```
71
+ dept total_salary headcount
72
+ 0 eng 345.0 3
73
+ 1 mkt 110.0 1
74
+ ```
75
+
76
+ ---
77
+
78
+ ## 📊 Performance — TPC-H at 1 M rows *(v0.3.0)*
79
+
80
+ MX CPU beats Polars on **20/22** queries. GPU advantage compounds at 10 M+ rows where kernel parallelism dominates PCIe upload cost.
81
+
82
+ | Query | MX CPU | MX GPU | Polars | CPU vs Polars |
83
+ |---|---:|---:|---:|---:|
84
+ | Q9 · Product profit (6-table join) | **0.6 ms** | 6.6 ms | 39.9 ms | **67×** |
85
+ | Q12 · 2-table join + agg | **0.5 ms** | 3.4 ms | 23.2 ms | **46×** |
86
+ | Q3 · 3-table join + agg | **2.6 ms** | 8.7 ms | 23.3 ms | **9×** |
87
+ | Q1 · Filter + 8 aggregations | **10.7 ms** | 42.1 ms | 33.3 ms | **3.1×** |
88
+
89
+ → [Full 22-query tables (1 M + 10 M rows), methodology, and reproduce instructions](docs/benchmarks.md)
90
+
91
+ ---
92
+
93
+ ## 📚 Docs
94
+
95
+ | | |
96
+ |---|---|
97
+ | [**API Reference**](docs/api.md) | LazyFrame, expressions, SQL frontend, supported operations, running tests |
98
+ | [**Benchmarks**](docs/benchmarks.md) | Full TPC-H tables, kernel catalogue, limitations, roadmap, reproduce instructions |
99
+ | [**Architecture**](docs/vision-and-architecture.md) | Design philosophy, internal layers, how MAX Graph fits in |
100
+ | [**Contributing**](CONTRIBUTING.md) | Dev setup, writing Mojo kernels, adding queries |
101
+
102
+ ---
103
+
104
+ ## 📦 Dependencies
105
+
106
+ | Package | Required | Purpose |
107
+ |---|---|---|
108
+ | `pyarrow >= 14` | ✅ | Column storage, zero-copy NumPy bridge |
109
+ | `numpy >= 1.24` | ✅ | Vectorized pre/post processing |
110
+ | `pandas >= 2.0` | ✅ | Reference implementations |
111
+ | `modular >= 26.4` | GPU only | MAX Engine runtime, Mojo GPU dispatch |
112
+ | `polars >= 0.20` | optional | Benchmark comparison |
113
+ | `sqlglot >= 25` | optional | SQL frontend parsing |
114
+
115
+ ---
116
+
117
+ ## 📄 License
118
+
119
+ Apache 2.0 — see [LICENSE](LICENSE).
@@ -1,6 +1,6 @@
1
1
  """mxframe - GPU-accelerated DataFrames with MAX Engine"""
2
2
 
3
- __version__ = "0.1.2"
3
+ __version__ = "0.3.0"
4
4
 
5
5
  # Lazy expression layer
6
6
  from .lazy_expr import Expr, col, lit, when, row_number