Horizontal Parallelism
About
The d9d.module.parallelism package provides functions that distribute modules across device meshes. These strategies are "horizontal": they split work within one pipeline stage. Pipeline parallelism is "vertical": it splits the model into stages of layers.
Design
DTensor-First
d9d requires every trainable parameter in a distributed run to be a torch.distributed.tensor.DTensor. This keeps the rest of the system simple:
- Checkpointing: The checkpointing engine does not need to know the parallel strategy. It reads
DTensor.placementsto decide how to gather, deduplicate and save each tensor. - Gradient synchronization: Gradient Synchronization reads the placements to find the mesh dimensions along which a parameter is replicated.
Composition over Monoliths
d9d does not use monolithic wrappers like torch.nn.parallel.DistributedDataParallel (DDP). DDP takes ownership of the whole model execution. Instead, d9d builds on PyTorch's parallelize_module API, which lets you choose a strategy for each submodule:
- Layer A can use tensor parallelism (row-wise or column-wise).
- Layer B, such as a router, can use replicate parallelism.
- Layer C, such as an MoE layer, can use expert parallelism.
Data parallelism is one more placement ("Replicate") in this system, so all strategies share one interface.
Strategies
Replicate Parallelism
parallelize_replicate replicates parameters across the mesh. Use it for data parallelism or context parallelism.
During the forward pass, the module sees its parameters as plain local torch.Tensor objects. Standard PyTorch operations and custom kernels therefore run without changes. Outside the forward pass, the parameters and the state dict hold DTensor objects.
Expert Parallelism (MoE)
parallelize_expert_parallel applies expert parallelism to an MoELayer:
- It shards the experts (the
GroupedLinearweights) along theep_shardmesh dimension, so each GPU holds a subset of experts. Alongep_replicate, the experts are replicated. - It replicates the router and the shared expert, if any, across the whole mesh.
- It switches the token dispatcher of the layer to DeepEP. This requires the
d9d[backend-expert-parallel-deepep]extra.
Fully Sharded Data Parallel (FSDP)
parallelize_fsdp is a thin wrapper around PyTorch's fully_shard. It differs from plain FSDP in two ways:
- Plain FSDP averages gradients across the mesh.
parallelize_fsdpsums them instead, because d9d normalizes gradients itself. parallelize_fsdprequires a 1D mesh. For a multi-dimensional mesh, useparallelize_hsdp, or first applyparallelize_replicateto the other dimensions.
Hybrid Sharded Data Parallel (HSDP)
parallelize_hsdp combines full sharding with replicate parallelism. It takes a multi-dimensional mesh and a shard_dim. It applies parallelize_fsdp along shard_dim and parallelize_replicate along all other dimensions. It skips dimensions of size 1.
Usage
The examples below use the mesh domains of Distributed Context. MyCustomLayer stands for your own module.
Replicate Parallelism
Expert Parallelism
FSDP
HSDP
API Reference
d9d.module.parallelism.api
Functions that apply horizontal parallelism strategies to modules.
parallelize_expert_parallel(module, mesh_experts, expert_shard_dim='ep_shard')
Applies expert parallelism to an MoE layer.
The sparse experts are sharded along expert_shard_dim and replicated along the other mesh
dimensions. The router and the shared expert (if any) are replicated across the whole mesh.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
MoELayer
|
The MoE layer to parallelize. |
required |
mesh_experts
|
DeviceMesh
|
The device mesh to distribute the layer over. |
required |
expert_shard_dim
|
str
|
The name of the mesh dimension to shard the experts along. |
'ep_shard'
|
parallelize_fsdp(module, mesh, *args, **kwargs)
Applies Fully Sharded Data Parallel (FSDP) with gradient summation.
The module is sharded with PyTorch's fully_shard over mesh. Unlike default FSDP, gradients
are summed across the mesh instead of averaged, and FSDP does not all-reduce them across
replicas. d9d normalizes and reduces gradients across replicas itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
Module
|
The module to shard. |
required |
mesh
|
DeviceMesh
|
The device mesh over which to shard the module. |
required |
*args
|
Any
|
Additional positional arguments passed to |
()
|
**kwargs
|
Any
|
Additional keyword arguments passed to |
{}
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the mesh does not have exactly one dimension. |
RuntimeError
|
If |
parallelize_hsdp(module, mesh, shard_dim='dp_cp_shard', *fsdp_args, **fsdp_kwargs)
Applies Hybrid Sharded Data Parallel (HSDP) to a module.
The module is sharded with FSDP along shard_dim and replicated along every other mesh
dimension. Dimensions of size 1 are skipped.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
Module
|
The module to parallelize. |
required |
mesh
|
DeviceMesh
|
The device mesh to distribute the module over. |
required |
shard_dim
|
str
|
The name of the mesh dimension to shard along. All other dimensions are replication dimensions. |
'dp_cp_shard'
|
*fsdp_args
|
Any
|
Positional arguments passed to the underlying FSDP parallelizer. |
()
|
**fsdp_kwargs
|
Any
|
Keyword arguments passed to the underlying FSDP parallelizer. |
{}
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the device mesh has no dimension names. |
parallelize_replicate(module, mesh)
Applies Replicate Parallelism to a module.
Parameters become DTensor objects with Replicate placements on every mesh dimension.
During the forward pass, the module computes with plain local tensors (see ToLocalParallel).
This is data parallelism expressed with DTensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
Module
|
The module to parallelize. |
required |
mesh
|
DeviceMesh
|
The device mesh to replicate the module over. |
required |
d9d.module.parallelism.style
Custom ParallelStyle implementations for d9d modules.
ShardMoESparseExpertsParallel
Bases: ParallelStyle
Parallel style that shards the experts of an MoELayer along one mesh dimension.
Every GroupedLinear weight in the layer is sharded along the expert dimension on the shard
mesh dimension and replicated on the other mesh dimensions. If the shard dimension has more than
one rank, the style also enables the layer's distributed token dispatch over that dimension.
__init__(shard_dim_name)
Constructs the ShardMoESparseExpertsParallel object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shard_dim_name
|
str
|
The name of the mesh dimension to shard the experts along. |
required |
ToLocalParallel
Bases: ParallelStyle
Parallel style that stores parameters as DTensor but computes with local tensors.
Parameters become DTensor objects with the given placements. During the forward pass, the
module sees them as local torch.Tensor objects. Use it for strategies such as Replicate, where
the module code is not DTensor-aware but gradient sync and checkpointing need DTensor.
__init__(param_placement, grad_placement)
Constructs the ToLocalParallel object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
param_placement
|
tuple[Placement, ...]
|
The placements of the parameters, one per mesh dimension. |
required |
grad_placement
|
tuple[Placement, ...]
|
The placements of the gradients, one per mesh dimension. They are passed to
|
required |