The d9d Project
d9d is a composable framework for distributed training in PyTorch. You do not fit your model into a framework's template: you write it in plain PyTorch and compose the job from d9d parts. d9d runs the job on one GPU or on a multi-node cluster. It combines data, fully sharded, tensor, context, expert and pipeline parallelism in one N-dimensional device mesh.
d9d is for researchers and engineers who change the model, the parallelism or the training method itself. Each change stays in their own code.
Alpha
d9d is in alpha, so public APIs can change between minor releases. Read the changelog before you upgrade.
Get Started
- Quickstart: Train a small model on one GPU and learn the parts of a job.
- How d9d Works: How the parts of a job fit together.
- Fine-Tune a Hugging Face Model: A complete job that loads Qwen3, trains it and exports it back.
- Table of Contents: Every page, with a short description.
Some features need extras, such as d9d[backend-sdpa-flash-attention-4]. See Installation.
What You Can Train
d9d runs the same job code from a quick experiment on one consumer GPU, such as an RTX 3090, to a large run on a multi-node cluster. You can use it for:
- LLM pre-training: Dense and MoE language models across many nodes. See Choosing Parallelism.
- Fine-tuning and post-training: Load a Hugging Face checkpoint, train all weights or LoRA adapters with your own loss, and export the model back. See Fine-Tune a Hugging Face Model.
- Reinforcement learning: Hand the GPUs to a rollout engine between training steps and take them back. See Colocated RL.
- Classifiers, embedding models and multi-head models: Put classification, embedding or several heads on a language model backbone, and track metrics such as AUROC and F1 across ranks. See Model Heads.
- New architectures: A model that no framework ships yet: a new attention variant, a recurrent or state-space model, or something that is not a transformer at all. Write it in plain PyTorch, reuse d9d blocks where they fit, and train it like any other d9d model. See Model Design.
- New parallelism strategies: A way to split a model that no framework offers yet, e.g. a new expert placement or a custom tensor-parallel layout for your own layer. Write it as a function that turns the parameters of a submodule into
DTensors with your placements. Gradient synchronization and checkpointing read the placements, so the rest of d9d works with it unchanged. See Horizontal Parallelism. - Evaluation and batch inference: Run a model over a dataset with the same data, model and parallelism code. See Inference Loop.
- Anything else that trains with a loss: The model, the data and the loss are your code, e.g. the regression model of the Quickstart.
What You Write
You write four parts: the data, the model, the task with the loss, and the model provider that builds and distributes the model. The data and the model are plain PyTorch, and the task and the model provider implement small d9d interfaces. d9d provides the rest, and you can replace any part. This is the Quickstart job, without its type parameters:
d9d owns the training loop: gradient synchronization and accumulation, clipping, checkpointing, logging and timeouts.
Scale Without Changing the Code
To train on 4 GPUs with fully sharded data parallelism, change the mesh in the config and launch the same script with torchrun:
The model provider decides how each submodule is distributed, so the strategy is your code, not a framework setting. See Choosing Parallelism.
Extend Without Forking
d9d is a package that you install, not a repository that you fork. Every part of a job is an interface, and your code implements it in your own project. To try a new idea, you write it next to your job and leave d9d untouched:
| To try | You write | See |
|---|---|---|
| A new model | An nn.Module with reset_parameters() and forward(inputs, shared). You can build it from d9d blocks such as attention, MoE and RMSNorm. |
Model Design |
| A new parallelism strategy | A function that distributes submodules over a device mesh, called from parallelize_model_stage(). |
Horizontal Parallelism |
| A new loss or training method | A TrainTask. |
User Tasks |
| A new data pipeline | A DataProvider. |
Data Loading |
| A new optimizer or LR schedule | An OptimizerProvider or an LRSchedulerProvider. |
Optimizer |
| A new checkpoint format | A state mapper. | Model State Mapper |
| A change to the loop | An event handler, e.g. one that runs RL rollouts between steps. | Event Bus and Hooks |
Updating d9d is then a version bump, not a rebase of your changes.
The same holds for AI coding agents. An agent changes your project, not the framework. It adds a model, a strategy or a task against a small interface and runs the job. There is no fork to patch and keep in sync.
How d9d Compares
Features converge between training frameworks, so d9d differs in how it is built:
- The strategy is your code, not a framework setting: Other frameworks write the split of each layer into the model code, or apply one mode to the whole model. In d9d, your model provider decides how each submodule is distributed.
- The model is yours: It is a standard
nn.Modulein your project that inherits no framework class and never reads a device mesh. With pipeline parallelism, it builds only the layers of its stage. - Checkpoints are graphs: Other frameworks convert Hugging Face checkpoints with a hand-written key map per model, or load the whole model on every rank. In d9d, a graph of state mappers streams checkpoints in and out without loading them into memory.
- Built on PyTorch primitives: Parallelism is
DTensorplacements on aDeviceMesh, applied withparallelize_module, and training checkpoints are PyTorch Distributed Checkpoints. What you know about PyTorch distributed applies directly. - Small components, wired explicitly: The training loop is a sequence of small components, such as the gradient manager, the clipper and the checkpointer. Each gets its collaborators and the
DistributedContextthrough its constructor, with no global process groups and no patches of PyTorch. Configs are Pydantic models, every hook gets a typed context, and all core code passes strict type checking, so you can follow a training step through a few files.
d9d and Other Frameworks compares these choices with Megatron-Core, torchtitan, DeepSpeed, Accelerate and others, lists the trade-offs of d9d and says when to choose another tool.
Community
- Discord: Join the d9d server for questions and discussions of distributed training.
- Issues: Report bugs and request features in the GitHub issue tracker.
- Contributing: Read CONTRIBUTING.md before you open a pull request.