Skip to main content

Datarax: A Data Pipeline Framework for JAX

CI codecov Build Summary

Project Status: Active


Early Development - API Unstable

Datarax is in early development and undergoing rapid iteration. Breaking changes are expected. Pin to specific commits if stability is required. We recommend waiting for a stable release (v1.0) before using Datarax in production.


Datarax (Data + Array/JAX) is an extensible data pipeline framework built for JAX-based machine learning workflows. It leverages JAX's JIT compilation, automatic differentiation, and hardware acceleration to build data loading, preprocessing, and augmentation pipelines that run on CPUs, GPUs, and TPUs.

Key Features

  • JAX-Native Design: All core components built on JAX's functional paradigm with Flax NNX module system for state management
  • High Performance: JIT-compiled pipelines via XLA, with built-in profiling and roofline analysis
  • DAG Pipelines: Graph-based construction via Pipeline.from_dag with branching, parallel execution, caching, and differentiable rebatching nodes
  • Scalability: Multi-device and multi-host data distribution with device mesh sharding
  • Determinism: Reproducible pipelines by default using Grain's Feistel cipher shuffling (O(1) memory), with resumable mid-epoch iteration for exact checkpoint/restore
  • Extensibility: Custom data sources, operators, and augmentation strategies via composable NNX modules
  • Benchmarking Suite: Comparative benchmarks against 14+ frameworks with calibrax-powered analysis and regression checks
  • Ecosystem Integration: Works with Flax, Optax, Orbax, HuggingFace Datasets, and TensorFlow Datasets

Why Datarax?

JAX has mature libraries for models (Flax), optimizers (Optax), and checkpointing (Orbax), but lacks a dedicated data pipeline framework that operates at the same level of abstraction. Existing options are either framework-agnostic loaders that return NumPy arrays (losing JIT/autodiff benefits) or wrappers around tf.data/PyTorch that introduce cross-framework overhead. Datarax aims to fill this gap. The framework is under active development with ongoing performance optimization — the architecture is functional, but throughput and API surface are still being refined.

JAX-Native from the Ground Up

Every component — sources, operators, batchers, samplers, sharders — is a Flax NNX module. Pipeline state is managed through NNX's variable system, which means operators can hold learnable parameters, be serialized with Orbax, and participate in JAX transformations (jit, vmap, grad) without special handling.

Differentiable Data Pipelines

Because operators are NNX modules, gradients flow through the entire pipeline. This enables approaches that are not possible with standard data loaders:

See the differentiable pipeline examples for details.

DAG Execution Model

Pipelines are directed acyclic graphs, not linear chains. Pipeline(stages=[...]) covers the sequential case; Pipeline.from_dag(...) builds arbitrary graphs whose nodes are NNX modules, with composition strategies (sequential, parallel, branching, merging, ensemble) handling multi-path logic. Graph nodes cover field routing (SplitField) and differentiable within-batch regrouping (RebatchNode), while CachingIterator memoizes at the iteration boundary.

Deterministic Reproducibility

Shuffling uses Grain's Feistel cipher permutation, which generates a full-epoch permutation in O(1) memory without materializing the index array. Stochastic operators are keyed on global record positions, so each record augments identically regardless of batch size, shuffle order, or host count. Iterating a random-access pipeline returns a stateful iterator whose get_state()/set_state() capture position and RNG counts for exact mid-epoch resume, and the live module stays consistent at every yield boundary so Orbax checkpoints taken inside a training loop restore the exact remaining stream.

Built-in Competitive Benchmarking

The benchmarking suite profiles datarax against 14 peer frameworks (Grain, tf.data, PyTorch DataLoader, DALI, Ray Data, and others) across 37 standardized scenarios. Results are converted to calibrax runs for direction-aware metrics, regression gating, and W&B export. This benchmark-driven loop is how datarax tracks progress toward competitive throughput — current results and optimization status are tracked in the benchmarking documentation.

Installation

# Basic installation
uv pip install datarax

# With data loading support (HuggingFace, TFDS, audio/image libs)
uv pip install "datarax[data]"

# With GPU support (CUDA 12)
uv pip install "datarax[gpu]"

# Full development installation
uv pip install "datarax[all]"

macOS / Apple Silicon

# macOS CPU mode (recommended)
uv pip install "datarax[all-cpu]"
JAX_PLATFORMS=cpu python your_script.py

# Metal GPU acceleration (experimental, M1/M2/M3+)
uv pip install jax-metal
JAX_PLATFORMS=metal python your_script.py

Note: Metal GPU acceleration is community-tested. CI runs on macOS with CPU only.

Quick Start

import jax
import jax.numpy as jnp
import numpy as np
from flax import nnx

from datarax import Pipeline
from datarax.operators import ElementOperator, ElementOperatorConfig
from datarax.sources import MemorySource, MemorySourceConfig
from datarax.typing import Element


def normalize(element: Element, key: jax.Array | None = None) -> Element:
    return element.update_data({"image": element.data["image"] / 255.0})


def augment(element: Element, key: jax.Array) -> Element:
    key1, _ = jax.random.split(key)
    flip = jax.random.bernoulli(key1, 0.5)
    new_image = jax.lax.cond(
        flip, lambda img: jnp.flip(img, axis=1), lambda img: img,
        element.data["image"],
    )
    return element.update_data({"image": new_image})


# Create in-memory data source
data = {
    "image": np.random.randint(0, 255, (1000, 28, 28, 1)).astype(np.float32),
    "label": np.random.randint(0, 10, (1000,)).astype(np.int32),
}
source = MemorySource(MemorySourceConfig(), data=data, rngs=nnx.Rngs(0))

# Build pipeline with DAG-based API
normalizer = ElementOperator(
    ElementOperatorConfig(stochastic=False), fn=normalize, rngs=nnx.Rngs(0),
)
augmenter = ElementOperator(
    ElementOperatorConfig(stochastic=True, stream_name="augmentations"),
    fn=augment, rngs=nnx.Rngs(42),
)

pipeline = (
    Pipeline(source=source, stages=[normalizer, augmenter], batch_size=32, rngs=nnx.Rngs(0))
)

# Process batches
for i, batch in enumerate(pipeline):
    if i >= 3:
        break
    print(f"Batch {i}: images {batch['image'].shape}, labels {batch['label'].shape}")

Advanced: Branching and Parallel DAGs

# Define additional operators
def invert(element: Element, key=None) -> Element:
    return element.update_data({"image": 1.0 - element.data["image"]})

inverter = ElementOperator(
    ElementOperatorConfig(stochastic=False), fn=invert, rngs=nnx.Rngs(0),
)

# Build a branching DAG:
# - augment and normalize each consume the source independently
# - merge takes both outputs and averages them
class Merge(nnx.Module):
    def __call__(self, augmented, clean):
        return {
            "image": (augmented["image"] + clean["image"]) / 2,
            "label": clean["label"],
        }

complex_pipeline = Pipeline.from_dag(
    source=source,
    nodes={"augment": augmenter, "normalize": normalizer, "merge": Merge()},
    edges={"augment": [], "normalize": [], "merge": ["augment", "normalize"]},
    sink="merge",
    batch_size=32,
    rngs=nnx.Rngs(0),
)

Architecture

src/datarax/
  core/         # Base modules: DataSourceModule, OperatorModule, Element, Batcher, Sampler, Sharder
  pipeline/     # Pipeline (nnx.Module): linear stages and Pipeline.from_dag for branching
  sources/      # MemorySource, TFDS (eager/streaming), HuggingFace (eager/streaming), ArrayRecord, MixDataSourcesNode, StreamingDiskSource
  operators/    # ElementOperator, MapOperator, CompositeOperator, modality-specific (image, audio)
    strategies/ # Sequential, Parallel, Branching, Ensemble, Merging composition strategies
  samplers/     # Sequential, Shuffle (Feistel cipher), Range, EpochAware, SlidingWindow, BufferSampler
  batching/     # DefaultBatcher with buffer state management
  sharding/     # ArraySharder, JaxProcessSharder for multi-device distribution
  distributed/  # DeviceMeshManager, data-parallel and sharding utilities
  checkpoint/   # Orbax integration (NNX-standard checkpoint pattern)
  monitoring/   # MetricsCollector, callbacks, reporters (console/file)
  performance/  # Roofline analysis, XLA optimization utilities
  control/      # Prefetcher for asynchronous data loading
  memory/       # Shared memory manager for multi-process data sharing
  workers/      # Reserved namespace for the planned multiprocessing backend
  config/       # TOML-based configuration system with schema validation
  cli/          # datarax CLI entry point
  utils/        # PyTree utilities, external integration helpers

Benchmarking

Datarax includes a benchmarking suite for comparison against 14 data loading frameworks across 37 workload scenarios (vision, NLP, tabular, multimodal, distributed).

# Install benchmark dependencies (adds PyTorch, DALI, Ray, etc.)
uv sync --extra benchmark

# Optional: install calibrax with W&B support explicitly
uv pip install "calibrax[wandb] @ git+https://github.com/avitai/calibrax.git"

# Run benchmarks locally
uv run python -m benchmarks.runners.full_runner --platform cpu --repetitions 5

# Run on cloud (SkyPilot)
sky launch benchmarks/sky/gpu-benchmark.yaml --env WANDB_API_KEY=$WANDB_API_KEY

Benchmark results are exported to W&B with charts, gap analysis, stability reports, and raw result artifacts. See Benchmarking Guide for methodology and cloud deployment.

Development Setup

Datarax uses uv as its package manager:

# Clone and setup
git clone https://github.com/avitai/datarax.git
cd datarax

# Automatic setup
./setup.sh && source activate.sh

# Or manual install
uv sync --extra dev

Running Tests

# CPU-only (most stable)
JAX_PLATFORMS=cpu uv run pytest

# Include benchmark test suite in the same run
JAX_PLATFORMS=cpu uv run pytest --all-suites

# Specific module
JAX_PLATFORMS=cpu uv run pytest tests/sources/test_memory_source_module.py

Docker

# Build and run
docker build -t datarax:latest .
docker run --rm --gpus all datarax:latest python -c "import datarax, jax; print(jax.devices())"

# Benchmark images
docker build -f benchmarks/docker/Dockerfile.gpu -t datarax-bench:gpu .

See Docker Guide for full details.

Documentation

License

Datarax is licensed under the MIT License.

Download files

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

Source Distribution

datarax-0.1.4.tar.gz (247.7 kB view details)

Uploaded Source

Built Distribution

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

datarax-0.1.4-py3-none-any.whl (301.9 kB view details)

Uploaded Python 3

File details

Details for the file datarax-0.1.4.tar.gz.

File metadata

  • Download URL: datarax-0.1.4.tar.gz
  • Upload date:
  • Size: 247.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for datarax-0.1.4.tar.gz
Algorithm Hash digest
SHA256 5d2b0e0d06bd77b41c792c91b66f304584b434ad2cc872da6f4dec14b0ca234f
MD5 8983d94919d38f2b6ba8bf4314ebb5b1
BLAKE2b-256 a2a3f88cdc2523c4ef698f0ec3493f79c03e7f5d25d2960263e2a1718a1850bb

See more details on using hashes here.

Provenance

The following attestation bundles were made for datarax-0.1.4.tar.gz:

Publisher: publish.yml on avitai/datarax

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

File details

Details for the file datarax-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: datarax-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 301.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for datarax-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 d0d45d9060925a67f531895dd218dd46b35708bf8a6eef4a6cd39985a6d93049
MD5 5f228533ceabc29ea467744893e4e05d
BLAKE2b-256 b7d875dbe99b986bf7158b11dff58783eed32a13a80f4990924d04586e284bde

See more details on using hashes here.

Provenance

The following attestation bundles were made for datarax-0.1.4-py3-none-any.whl:

Publisher: publish.yml on avitai/datarax

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