Name Date Size #Lines LOC

..--

_ops/H25-Apr-2025-4,9263,821

debug/H25-Apr-2025-1,3501,008

examples/H25-Apr-2025-1,5181,201

experimental/H25-Apr-2025-1,8201,490

parallel/H25-Apr-2025-1,9001,500

README.mdH A D25-Apr-202512.1 KiB178129

__init__.pyH A D25-Apr-20251.8 KiB6854

_api.pyH A D25-Apr-202551.6 KiB1,232952

_collective_utils.pyH A D25-Apr-202513.2 KiB374268

_dispatch.pyH A D25-Apr-202521 KiB511414

_dtensor_spec.pyH A D25-Apr-202510.1 KiB277217

_op_schema.pyH A D25-Apr-202516.8 KiB458346

_random.pyH A D25-Apr-202515.5 KiB382290

_redistribute.pyH A D25-Apr-202514.1 KiB352265

_sharding_prop.pyH A D25-Apr-202521 KiB498388

_shards_wrapper.pyH A D25-Apr-202511.3 KiB317245

_tp_conv.pyH A D25-Apr-20259.9 KiB280208

_utils.pyH A D25-Apr-202513.7 KiB317242

device_mesh.pyH A D25-Apr-2025190 107

placement_types.pyH A D25-Apr-202524.9 KiB653506

README.md

1# PyTorch DTensor (Prototype Release)
2
3This folder contains the DTensor (a.k.a DistributedTensor) implementation in PyTorch.
4
5## Introduction
6We propose distributed tensor primitives to allow easier distributed computation authoring in SPMD(Single Program Multiple Devices) paradigm. The primitives are simple but powerful when used to express tensor distributions with both sharding and replication parallelism strategies. This could empower native Tensor parallelism among other advanced parallelism explorations. For example, to shard a big tensor across devices with 3 lines of code:
7
8```python
9# to run this file (i.e. dtensor_example.py):
10# torchrun --standalone --nnodes=1 --nproc-per-node=4 dtensor_example.py
11import os
12import torch
13from torch.distributed._tensor import init_device_mesh, Shard, distribute_tensor
14
15# Create a mesh topology with the available devices:
16# 1. We can directly create the mesh using elastic launcher, (recommended)
17# 2. If using mp.spawn, one need to initialize the world process_group first and set device
18#   i.e. torch.distributed.init_process_group(backend="nccl", world_size=world_size)
19
20mesh = init_device_mesh("cuda", (int(os.environ["WORLD_SIZE"]),))
21big_tensor = torch.randn(100000, 88)
22# Shard this tensor over the mesh by sharding `big_tensor`'s 0th dimension over the 0th dimension of `mesh`.
23my_dtensor = distribute_tensor(big_tensor, mesh, [Shard(dim=0)])
24```
25
26## Motivation
27
28Today there are mainly three ways to scale up distributed training: Data Parallel, Tensor Parallel and Pipeline Parallel. Each of them works on a separate dimension where solutions have been built independently (i.e. PyTorch DDP, FSDP, ShardedTensor, PiPPy, etc.). When training really large models, users would like to use these technologies together (i.e. 3-D Parallelism), while the interoperability of the existing solutions are not great and often hard to use (i.e. users might want arbitrary combinations of the data parallel, tensor parallel and pipeline parallel). This is becoming an issue for users and one of the biggest reasons is that there is no common abstraction that build the bridge between different parallelism strategies.
29
30An ideal scenario is that users could build their distributed program just like authoring in a single node/device, without worrying about how to do distributed training in a cluster, and our solutions could help them run distributed training in an efficient manner. For example, researchers just need to build the big transformer model, and PyTorch Distributed automatically figures out how to split the model and run pipeline parallel across different nodes, how to run data parallel and tensor parallel within each node. In order to achieve this, we need some common abstractions to distribute tensor values and distributed computations accordingly.
31
32There're many recent works that working on tensor level parallelism to provide common abstractions, see the `Related Works` in the last section for more details. Inspired by [GSPMD](https://arxiv.org/pdf/2105.04663.pdf), [Oneflow](https://arxiv.org/pdf/2110.15032.pdf) and [TF’s DTensor](https://www.tensorflow.org/guide/dtensor_overview), we introduce PyTorch DTensor as the next generation of ShardedTensor to provide basic abstractions for distributing storage and computation. It serves as one of the basic building blocks for distributed program translations and describes the layout of a distributed training program. With the DTensor abstraction, we can seamlessly build parallelism strategies such as tensor parallelism, DDP and FSDP.
33
34## Value Proposition
35
36PyTorch DTensor primarily:
37-   Offers a uniform way to save/load `state_dict` during checkpointing, even when there’re complex tensor storage distribution strategies such as combining tensor parallelism with parameter sharding in FSDP.
38-   Enables Tensor Parallelism in eager mode. Compared to ShardedTensor, DistributedTensor allows additional flexibility to mix sharding and replication.
39-   Serves as the entry point of an SPMD programming model and the foundational building block for compiler-based distributed training.
40
41## PyTorch DTensor
42
43### DTensor API
44
45We offer both a lower level DistributedTensor API and a module level API to create a `nn.Module` with “distributed” parameters.
46
47#### Basic DTensor API Examples
48
49Here are some basic DTensor API examples that showcase:
501. How to construct a DTensor directly, to represent different types of sharding, replication, sharding + replication strategies.
512. How to create DTensor from a local `torch.Tensor`.
523. How to “reshard” an existing DTensor to a different DTensor with modified placement strategy or world size.
53
54```python
55# torchrun --standalone --nnodes=1 --nproc-per-node=4 dtensor_example.py
56import torch
57from torch.distributed._tensor import DTensor, Shard, Replicate, distribute_tensor, distribute_module, init_device_mesh
58
59# construct a device mesh with available devices (multi-host or single host)
60device_mesh = init_device_mesh("cuda", (4,))
61# if we want to do row-wise sharding
62rowwise_placement=[Shard(0)]
63# if we want to do col-wise sharding
64colwise_placement=[Shard(1)]
65
66big_tensor = torch.randn(888, 12)
67# distributed tensor returned will be sharded across the dimension specified in placements
68rowwise_tensor = distribute_tensor(big_tensor, device_mesh=device_mesh, placements=rowwise_placement)
69
70# if we want to do replication across a certain device list
71replica_placement = [Replicate()]
72# distributed tensor will be replicated to all four GPUs.
73replica_tensor = distribute_tensor(big_tensor, device_mesh=device_mesh, placements=replica_placement)
74
75# if we want to distributed a tensor with both replication and sharding
76device_mesh = init_device_mesh("cuda", (2, 2))
77# replicate across the first dimension of device mesh, then sharding on the second dimension of device mesh
78spec=[Replicate(), Shard(0)]
79partial_replica = distribute_tensor(big_tensor, device_mesh=device_mesh, placements=spec)
80
81# create a DistributedTensor that shards on dim 0, from a local torch.Tensor
82local_tensor = torch.randn((8, 8), requires_grad=True)
83rowwise_tensor = DTensor.from_local(local_tensor, device_mesh, rowwise_placement)
84
85# reshard the current row-wise tensor to a colwise tensor or replicate tensor
86colwise_tensor = rowwise_tensor.redistribute(device_mesh, colwise_placement)
87replica_tensor = colwise_tensor.redistribute(device_mesh, replica_placement)
88```
89
90#### High level User Facing APIs
91
92Users can use DTensor tensor constructors directly to create a distributed tensor (i.e. `distributed.ones/empty`), but for existing modules like `nn.Linear` that are already having `torch.Tensor` as parameters, how to make them distributed parameters? We offer a way to directly distribute a `torch.Tensor` and a module level APIs to directly distribute the module parameters. Below is the high level API we introduce:
93
94```python
95def distribute_tensor(tensor: torch.Tensor, device_mesh: DeviceMesh=None, placements: List[Placement]=None):
96    '''
97    distribute the tensor according to device_mesh and placements, `tensor` could be a "meta" tensor.
98    '''
99
100def distribute_module(
101    module: nn.Module,
102    device_mesh: DeviceMesh=None,
103    partition_fn: Callable[[str, nn.Module, DeviceMesh], ...]=None,
104    input_fn: Callable[...., None]=None,
105    output_fn: Callable[...., None]=None,
106):
107    '''
108    This function converts all module parameters to distributed tensor parameters according to the `partition_fn` specified.
109    It could also control the input/output of the module by specifying the `input_fn` and `output_fn`.
110    '''
111```
112
113#### High level API examples:
114
115```python
116import torch.nn as nn
117from torch.distributed._tensor import Shard, distribute_tensor, distribute_module, init_device_mesh
118
119class MyModule(nn.Module):
120    def __init__(self) -> None:
121        super().__init__()
122        self.fc1 = nn.Linear(8, 8)
123        self.fc2 = nn.Linear(8, 8)
124        self.relu = nn.ReLU()
125
126    def forward(self, input):
127        return self.relu(self.fc1(input) + self.fc2(input))
128
129mesh = init_device_mesh("cuda", (4,))
130
131def shard_params(mod_name, mod, mesh):
132    col_linear_placement = [Shard(0)]
133    # shard fc1 and fc2
134    if isinstance(mod, nn.Linear):
135        for name, param in mod.named_parameters():
136            dist_param = nn.Parameter(
137                distribute_tensor(param, mesh, col_linear_placement)
138            )
139            mod.register_parameter(name, dist_param)
140
141sharded_module = distribute_module(MyModule(), mesh, partition_fn=shard_params)
142
143```
144
145## Compiler and PyTorch DTensor
146
147DTensor provides efficient solutions for cases like Tensor Parallelism. But when using the DTensor's replication in a data parallel fashion, it might become observably slower compared to our existing solutions like DDP/FSDP. This is mainly because DDP/FSDP have a global view of the entire model architecture, thus could optimize for data parallel specifically, i.e. collective fusion and computation overlap, etc. In contrast, DistributedTensor as a Tensor-like object can only optimize within individual tensor operations.
148
149To improve efficiency of DTensor-based data parallel training, we are exploring a compiler-based solution on top of DTensor, which can extract graph information from user programs to expose more performance optimization opportunities.
150
151## Related Works
152
153This work is mainly inspired by [GSPMD](https://arxiv.org/pdf/2105.04663.pdf), [Oneflow](https://arxiv.org/pdf/2110.15032.pdf) and [TF’s DTensor](https://www.tensorflow.org/guide/dtensor_overview). All of these three works use a single “distributed tensor” concept for both replication and sharding, and the solutions could enable users to build up their distributed training program in a uniform SPMD programming model. Specifically:
154
155GSPMD:
156-   GSPMD is now the fundamental component of JAX/TensorFlow distributed training and enables various optimizations with the XLA compiler to allow users to train their models efficiently in a large scale setting.
157-   Fundamentally, GSPMD have three types of sharding strategies within a tensor: “tiled”, “replicated”, “partially tiled” to represent sharding and replication.
158-   At the core of GSPMD Partitioner, it utilizes the XLA compiler to do advanced optimizations, i.e. sharding propagation and compiler based fusion.
159-   XLA mark_sharding API: PyTorch XLA’s [mark_sharding](https://github.com/pytorch/xla/pull/3476) API uses [XLAShardedTensor](https://github.com/pytorch/xla/issues/3871) abstraction (i.e. sharding specs) in PyTorch/XLA. Under the hood XLAShardedTensor is utilizing the GSPMD partitioner to enable SPMD style training on TPU.
160
161OneFlow GlobalTensor:
162
163-  OneFlow is building up their own solution of the “GlobalTensor” concept, which is a variant form of GSPMD sharding, allowing users to explore different parallel strategies with GlobalTensor.
164-  OneFlow also has three types of tensor, but they are slightly different from GSPMD: “split”, “broadcast”, and “partial sum”. They don’t use partially tiled and instead have a concept of partial sum to partition the values.
165
166TensorFlow DTensor:
167-   [DTensor Concepts](https://www.tensorflow.org/guide/dtensor_overview) is an extension of TensorFlow synchronous distributed training. its sharding API, supported features and its compilation passes with MLIR.
168-   DTensor also allows sharding and replication on an n-d mesh like device network.
169-   DTensor implements MLIR passes to do propagation and operator implementations.
170
171There are also several cutting edge research fields that embeds tensor sharding as part of the system, i.e. [Megatron-LM](https://arxiv.org/pdf/1909.08053.pdf) for tensor parallelism on Transformer based models. [DeepSpeed](https://github.com/microsoft/DeepSpeed) for training large scale models with different optimization techniques on top of tensor sharding.
172
173### Additional context
174
175RFC: https://github.com/pytorch/pytorch/issues/88838
176
177We are gathering early feedbacks about this proposal. We have also posted this [RFC](https://dev-discuss.pytorch.org/t/rfc-pytorch-distributedtensor/740) to the dev-discuss forum, please feel free to comment directly in the above issue or in the forum post. To see a complete design doc with additional details about DTensor, please refer to this [doc](https://docs.google.com/document/d/1nFeJ8NSFNhNlCkNgWK31ZGRqm1L9rd0i_XN_RprphaI/edit#heading=h.6sovjqv9jiqn)
178