# mypy: 允许未类型化装饰器
# mypy: 允许未类型化定义
© Meta Platforms, Inc. 及其关联公司
导入
检查
导入
警告
来自 collections.abc
导入
序列
来自
打字
导入
任意,
可调用,
角色,
可选
来自 typing_extensions
导入
已弃用
导入
火炬
导入 torch.distributed.tensor._dispatch
作为 op_dispatch
导入 torch.distributed.tensor._random
作为
随机
导入 torch.nn
作为
然后
来自 torch.distributed.device_mesh
导入
_网状资源,
设备网格
来自 torch.distributed.tensor._collective_utils
导入
检查张量元数据,
网格广播
来自 torch.distributed.tensor._dtensor_spec
导入 DTensorSpec,
张量元
来自 torch.distributed.tensor._redistribute
导入 (
重新分配,
重新分配本地张量,
)
来自 torch.distributed.tensor._utils
导入 (
计算全局张量信息,
计算局部形状和全局偏移,
标准化到 torch 大小,
)
来自 torch.distributed.tensor.placement_types
导入 (
部分支持,
放置,
复制,
片段,
)
__all__ = [
DTensor,
"分布式张量",
"分布式模块",
"个",
"空的",
全部,
随机,
"randn",
零,
]
aten = 火炬.
操作.aten
# [PyTorch 张量之间的自动微分交互]
#
# 下面定义的自动微分函数正在被公共 API 使用
# (例如,from_local,to_local)以确保 DTensor 与 torch.Tensor
# 在自动微分引擎中协同工作。这
# 允许 DTensor 只存在于模块层次结构的一部分。
#
# 例如,我们有一个由子模块组成的模块
# A、B 和 C,执行流程如下:
# 输入(torch.Tensor) -> 模块 A -> 模块 B -> 模块 C -> 输出(torch.Tensor)
#
# 仅希望将模块 B 做成分片模块
# DTensor 参数,以下的前向/反向应该可以工作:
#
# 输入(torch.Tensor) -> 模块 A
# -> DTensor 输入(from_local)-> 分片模块 B -> DTensor 输出
# -> torch.Tensor 输出 (to_local) -> 模块 C
#
# 所以 from_local/to_local 必须是 Autograd 函数。
#
类 _ToTorchTensor(
火炬.
自动微分.
函数):
@staticmethod
def 前向(
# 类型:忽略[覆盖]
ctx,
输入:
DTensor,
grad_placements: 可选[
序列[
放置]],
):
ctx.dtensor 规范 =
输入._spec
ctx.梯度放置 =
梯度放置
本地张量 =
输入._local_tensor
需要在此处返回一个新的 Tensor 对象,作为自动微分元数据
# 将被放入其中。所以我们不想污染 Tensor
# 对象存储在此 DTensor 的_local_tensor 中。
返回
本地张量.
以查看方式(
本地张量)
@staticmethod
def 反向(ctx, grad_output:
火炬.
张量):
# 类型:忽略[覆盖]
dtensor_spec = ctx.dtensor_spec
网格 =
dtensor 规范.
网格
梯度放置 = ctx.
梯度放置
dtensor 元数据 =
dtensor 规范.
张量元数据
_, 张量步长 =
计算全局张量信息(
grad_output, 网格,
dtensor 规范.
布局
)
张量步长 =
元组(
张量步长)
梯度放置 =
梯度放置
或
dtensor 规范.
布局
梯度规范 = DTensorSpec(
网格,
梯度放置,
张量元=
张量元(
shape=dtensor 元数据.shape,
步长=
张量步长,
数据类型=
dtensor 元数据.
数据类型,
),
)
返回 (
DTensor(
grad_output,
毕业规范,
需要梯度=grad_output.
需要梯度,
),
无,
)
类 _FromTorchTensor(
火炬.
自动微分.
函数):
@staticmethod
def 前向(
# 类型:忽略[覆盖]
ctx, # pyre 忽略[2]: 参数必须进行注解。
输入:
火炬.
张量,
装置网状结构:
设备网状结构,
安排:
元组[
放置, ...
]
运行检查:
布尔,
shape: 可选[
火炬.
尺寸] =
无,
步长:
可选[
元组[int, ...]] =
无,
) -> DTensor:
ctx.上次放置 =
布局
ctx.上次设备网格 =
设备网状
如果
形状
和
步长:
张量形状,
张量步长 = shape,
步长
elif not 形状
和 not
步长:
# 如果不是默认的 run_check,我们假设用户确定每个
# 级别具有相同的张量形状,我们只需使用那个来计算
全局形状
全局形状, global_stride =
计算全局张量信息(
输入,
装置网状结构,
布局
)
张量形状,
张量步长 =
火炬.
尺寸(
全局形状),
元组(global_stride)
否则:
提升
运行时错误(
f"找到形状:"{shape}
, 步长:{
步长}.",
"请同时传递形状和步长。",
)
如果
装置网状结构.
获取坐标()
是
无:
如果全局排名不参与设备网格,则
简单地将局部张量设置为空张量
输入 =
输入.
新空(0,
需要梯度=
输入.
需要梯度)
elif 运行检查:
# TODO: 支持全局形状/步长未传递时的不均匀分片
# 在检查 tensor_meta 期间构建全局 TensorMeta
check_shape_stride = not 形状
和 not
步长
检查张量元数据(
输入,
检查形状步长=
检查形状步长)
# TODO: 查看是否需要运行此 run_check 逻辑
相应的逆向
为
索引,
位置
在
列举(
安排):
如果
布置.
复制():
# 将广播排名为 0 的 tensor 广播到所有 rank
# 只有当 run_check 为 True 时才进行广播
输入 =
输入.
连续()
网格广播(
输入,
装置网状结构,
网格维度=
索引)
分布规范 = DTensorSpec(
装置网状结构,
安排,
张量元=
张量元(
张量形状,
张量步长,
输入.
数据类型,
),
)
# 我们想要一个与输入张量共享内存的新张量对象
dist_tensor = DTensor(
输入.
以查看方式(
输入),
dist_spec,
# dist tensor 的 requires_grad 依赖于输入是否
# requires_grad 或不
需要梯度=
输入.
需要梯度,
)
返回 dist_tensor
@staticmethod
def 反向(ctx, grad_output:
DTensor):
# 类型:忽略[覆盖]
上次放置 = ctx.
上次放置
上次设备网格 = ctx.
上次设备网格
# 在创建分布式张量时重新分配到放置位置
# 以确保梯度布局匹配,我们可以直接返回
# 本地梯度
如果 grad_output.
布局 !=
前置放置:
当前规范 = grad_output._spec
目标规范 = DTensorSpec(
前置设备网格,
前置放置,
张量元=grad_output.
规范.
张量元,
)
本地张量 = grad_output._local_tensor
输出 =
重新分配本地张量(
本地张量,
当前规范,
目标规范,
是否反向=
真实
)
# TODO: 直接返回重新分配的本地张量,无需
# 可微反向。检查这适用于所有情况是否合理。
返回
输出,
无,
无,
无,
无,
无
# TODO: 现在反向也是可微分的了,添加测试
# 测试更高层次的梯度。
返回 grad_output.
本地化(),
无,
无,
无,
无,
无
类 DTensor(
火炬.
张量):
""
``DTensor``(分布式张量)是 ``torch.Tensor`` 的子类,它提供了类似单设备的功能
抽象化以多设备 `torch.Tensor` 编程。它描述了分布式张量分片
布局(DTensor 布局)通过 :class:`DeviceMesh` 和以下类型的 :class:`Placement`:
* :class:`Shard`: 在 ``DeviceMesh`` 维度的设备上,沿张量维度 ``dim`` 分片的张量
* :class:`Replicate`: 在 ``DeviceMesh`` 维度的设备上复制的 Tensor
* :class:`Partial`: 张量在 ``DeviceMesh`` 维度的设备上正在等待缩减
当调用 PyTorch 运算符时,``DTensor`` 会覆盖 PyTorch 运算符以执行分片计算并在必要时进行通信。
与运算符计算一起,``DTensor`` 将正确地转换或传播放置(DTensor 布局),并根据运算符本身的语义生成新的 ``DTensor`` 输出。
当调用 PyTorch 运算符时,``DTensor`` 会覆盖 PyTorch 运算符以执行分片计算并在必要时进行通信。与运算符计算一起,``DTensor`` 将正确地转换或传播放置(DTensor 布局),并根据运算符本身的语义生成新的 ``DTensor`` 输出。
确保在调用 PyTorch 操作符时 ``DTensor`` 分片计算的数值正确性,``DTensor``
需要操作符的每个 Tensor 参数都是 DTensor。
.. note:: 在此处直接使用 Tensor 子类构造函数不是推荐创建 ``DTensor``
的方法(即它无法正确处理 autograd,因此不是公共 API)。请参阅 `create_dtensor`_
查看如何创建一个 ``DTensor`` 的部分。
"源代码"
_本地张量:
火炬.
张量
规范: DTensorSpec
__slots__ = ["_局部张量", "_spec"]
# _op_dispatcher 实例作为类属性以处理运行时调度逻辑
_op_dispatcher: op 分发.
Op 分发器 =
op 分发.
沉浸式翻译器()
@staticmethod
@torch.禁用 dynamo
def __new__(
类,
本地张量:
火炬.
张量,
规格: DTensorSpec,
*,
需要梯度:
布尔,
) -> DTensor:
""
从本地张量、设备网格和放置以及其他张量属性(例如形状、requires_grad、strides 等)构造一个 DTensor。
注意:这不是一个公开 API,它仅应被操作实现和内部使用。如果您想构造一个
.. 注意 :: 这不是一个公开 API,它仅应被操作实现和内部使用。如果您想构造一个
注意:这不是一个公开 API,它仅应被操作实现和内部使用。如果您想构造一个
从本地张量创建 DTensor,请考虑使用`DTensor.from_local`。
您想从一个“全局”张量(其中)构造一个 DTensor
已经初始化了张量,并想要对这个张量进行分片)
考虑使用 `distribute_tensor`。
"源代码"
如果
本地张量.requires_grad
和 not
需要梯度:
warnings.警告(
"从 torch.Tensor 构建 DTensor 时,建议使用"
"local_tensor.detach()并确保 requires_grad 一致性。"
)
# 新方法指导从 local_tensor 创建包装张量并添加
# 放置规范,它不会进行实际分布
断言
规格.
张量元数据
是 not
无,
"TensorMeta 不能为空!"
r = 火炬.
张量._make_wrapper_subclass(
# 类型: 忽略[attr-defined]
类,
规格.
张量元.shape,
strides=规格.
张量元.
步长,
数据类型=
本地张量.
数据类型,
设备=
本地张量.
设备,
布局=
本地张量.
布局,
需要梯度=
需要梯度,
)
r._spec = 规范
r._local_tensor = 本地张量
返回 r
# pyre-fixme[14]: `__repr__` 方法在 `DTensor` 中不一致地覆盖。
# pyre-fixme[3]: 返回类型必须进行注解。
def __repr__(我):
# 类型:忽略[覆盖]
考虑对所有本地张量进行_all_gather 以更好地进行调试
返回 f
"DTensor(本地张量={
我.
_本地张量}
,设备网格={
我.
规范.
网格}, placements={
我.
规范.
安排})"
def __张量展平__(
我):
""
DTensor 转换为本地张量的协议
用于 PT2 追踪的协议
"源代码"
返回 [
"_局部张量"
] (
我.
规范,
我.
需要梯度)
@staticmethod
def __张量展开__(
内部张量,
展平规范,
外部尺寸,
外部步长):
断言
展平规范
是 not
无, (
"期望从 `__tensor_flatten__` 返回值中获取非 None 的 spec!"
)
本地张量 =
内部张量[
"_局部张量"]
规格, requires_grad =
展平规范
展平张量元数据 =
张量元(
shape=外部尺寸,
步长=
外部步长,
数据类型=
规格.
张量元.
数据类型,
)
展开_spec = DTensorSpec(
规格.
网格,
规格.
安排,
张量元=
展平张量元数据,
)
返回 DTensor(
本地张量,
展平规范,
需要梯度=
需要梯度,
)
def 强制转换切线元数据(
我):
如果 not
任何(isinstance(p,
部分支持)
为 p
在
我.
安排):
返回 self
布局 = [
复制()
如果 isinstance(p,
部分支持)
否则 p
为 p
在
我.
布局
]
返回
我.
重新分配(
装置网状结构=
我.
装置网状结构,
安排=
安排)
def __coerce_same_metadata_as_tangent__(我,
展平规范,
预期类型=
无):
如果
预期类型
是 not
无:
返回
无
(规格, _) =
展平规范
tensor_flatten()的结果
返回
我.
重新分配(
装置网状结构=
我.
装置网状结构,
安排=
规格.
安排,
)
@classmethod
@torch.禁用 dynamo
# pyre-fixme[3]: 返回类型必须进行注解。
# pyre-fixme[2]: 参数必须进行注解。
def __torch_dispatch__(类,
函数,
类型,
参数=(), kwargs=
无):
返回 DTensor._op_dispatcher.
调度(
函数,
参数,
kwargs 或 {},
)
[文档] @staticmethod
def 从本地(
本地张量:
火炬.
张量,
装置网状结构:
可选[
设备网状结构] =
无,
安排:
可选[
序列[
放置]] =
无,
*,
运行检查:
布尔类型 =
错误,
shape: 可选[
火炬.
尺寸] =
无,
步长:
可选[
元组[int, ...]] =
无,
) -> DTensor:
""
从每个 rank 的本地 torch.Tensor 创建一个:class:`DTensor`。
根据指定的`device_mesh`和`placements`进行。
参数:
local_tensor (torch.Tensor):每个 rank 的本地 torch.Tensor。
device_mesh (:class:`DeviceMesh`, optional): 可选的 DeviceMesh,用于放置
张量,如果未指定,必须在设备网格下调用
上下文管理器,默认:None
放置(List[:class:`Placement`],可选):放置列表
描述了如何在 DeviceMesh 上放置本地 torch.Tensor,必须
具有与 `device_mesh.ndim` 相同的元素数量。
关键字参数:
run_check(布尔值,可选):以额外的通信成本,在各个 rank 之间执行
精确检查,以检查每个本地张量的元信息
确保正确性。如果`placements`中有`:class:`Replicate`,则
设备网格维度的第一排数据将被广播到其他排。默认:False
形状(torch.Size,可选):一个指定大小的 int 列表
形状(torch.Size,可选):一个指定大小的 int 列表
基于 `local_tensor` 构建的 DTensor。请注意,如果 ``local_tensor`` 的形状在不同排名之间不同,则需要提供。
如果不提供,``shape`` 将根据给定的分布式张量均匀分片到各个排名来计算。默认:None
如果不提供,``shape`` 将根据给定的分布式张量均匀分片到各个排名来计算。默认:None
张量在各个 rank 上均匀分配。默认:无
步长(tuple,可选):一个指定 DTensor 步长的 int 列表。
如果不提供,将假设给定的分布式
张量在各个 rank 上均匀分配。默认:无
返回:
一个 `DTensor` 对象
.. 注意:: 当 ``run_check=False`` 时,确保用户传入的本地张量在各个 rank 之间正确(即张量在 ``Shard(dim)`` 放置或 ``Replicate()`` 放置时已分片)。否则,创建的 DTensor 的行为是未定义的。
如果不是,则创建的 DTensor 的行为是未定义的。
如果不是,则创建的 DTensor 的行为是未定义的。
如果不是,则创建的 DTensor 的行为是未定义的。
.. 注意:: ``from_local`` 是可微分的,创建的 `requires_grad` 对象将取决于 `local_tensor` 是否需要梯度。
`DTensor` 对象的 `requires_grad` 将取决于 `local_tensor` 是否需要梯度。
"源代码"
# 如果形状/数据类型相同,则无需运行_check,如果不同,则必须进行 allgather。
# 检查跨 rank 的元数据以检查大小/数据类型。
除非有复制,否则不应有数据通信
其中我们广播来自第一个排名的复制策略
在网格维度中
设备网状 =
设备网状
或
_网状资源.
获取当前网状()
设备类型 =
装置网状结构.
设备类型
根据设备网格的 device_type 将本地张量转换为所需的设备
如果
设备类型 !=
本地张量.
设备.
类型
和 not
本地张量.
是否是元数据:
本地张量 =
本地张量.
到(
设备类型)
如果没有指定,则将默认放置设置为复制
如果
布局
是
无:
布局 = [
复制()
为 _
在
范围(
装置网状结构.ndim
]
否则:
布局 =
列表(
安排)
为
索引,
位置
在
列举(
安排):
将碎片维度标准化为正值
如果
布置.is_shard():
位置 =
角色(
片段,
布置)
如果
布置.
维度 < 0:
安排[
索引] =
片段(
布置.
维度 +
本地张量.ndim)
`from_local` 可微,该函数创建的 dist 张量的梯度应该反向传播到 local_tensor,因此我们调用一个自动微分函数来构建 dist 张量。
应该将梯度反向传播到 local_tensor,因此我们调用一个自动微分函数来构建 dist 张量。
应该将梯度反向传播到 local_tensor,因此我们调用一个自动微分函数来构建 dist 张量。
返回 _FromTorchTensor.
应用(
# pyre-ignore[16]: 自动微分函数
本地张量,
装置网状结构,
元组(
安排),
运行检查,
shape,
步长,
)
[文档] def to_local(
self, *, grad_placements: Optional[Sequence[放置]] = None
) -> torch.Tensor:
"""
获取此 DTensor 在其当前秩上的本地张量。对于分片,它返回
一个逻辑张量视图的本地分片,在复制时返回副本
其当前排名。
关键词参数:
grad_placements (List[:class:`Placement`], 可选): 描述了
该函数返回的 Tensor 的任何梯度布局的未来布局。
`to_local` 将 DTensor 转换为本地张量,并返回本地张量。
`to_local` 将 DTensor 转换为本地张量,并返回本地张量。
可能不会在代码后续中用作原始 DTensor 布局。这个参数是用户提供给 autograd 的提示,如果返回的张量布局与原始 DTensor 布局不匹配。
如果未指定,我们将假设梯度布局保持不变。
如果返回的张量布局与原始 DTensor 布局不匹配,用户可以提供这个参数作为给 autograd 的提示。
如果未指定,我们将假设梯度布局保持与原始相同。
作为原始 DTensor 使用,并以此进行梯度计算。
返回:
一个 :class:`torch.Tensor` 或 ``AsyncCollectiveTensor`` 对象。它代表当前 rank 上的本地张量。当返回 ``AsyncCollectiveTensor`` 对象时,
本地张量。当返回 ``AsyncCollectiveTensor`` 对象时,
这意味着本地张量尚未准备好(即通信尚未完成)。在这种情况下,用户需要调用 `wait` 来等待本地张量准备好。
在此情况下,用户需要调用 `wait` 来等待本地张量准备好。
.. 注意:: `to_local` 是可微分的,返回的本地张量的 `requires_grad` 将取决于 `DTensor` 是否需要梯度。
注意:`to_local` 是可微分的,返回的本地张量的 `requires_grad` 将取决于 `DTensor` 是否需要梯度。
"""
如果没有启用 torch.is_grad_enabled()
返回 self._local_tensor
如果 grad_placements 不是 None 且不是 tuple 类型
grad_placements = tuple(grad_placements)
return _ToTorchTensor.apply(
self, grad_placements
) # pyre-ignore[16]: autograd func
[文档] def
重新分配(
我,
装置网状结构:
可选[
设备网状结构] =
无,
安排:
可选[
序列[
放置]] =
无,
*,
async_op: 布尔类型 =
错误,
) -> DTensor:
""
``redistribute`` 执行必要的集体操作,重新分配当前
DTensor 从其当前放置位置重新分配到新的放置位置,或者从其当前 DeviceMesh
重新分配到新的 DeviceMesh。例如,我们可以通过指定 DeviceMesh 每个维度的 Replicate 放置
来将分片 DTensor 转换为复制的 DTensor。
当从当前位置重新分配到同一设备网格维度的新位置时,我们
将执行以下操作,包括通信集体或本地操作:
碎片(维度)-> 复制():all_gather
2. ``Shard(src_dim)`` -> ``Shard(dst_dim)``: 全全映射
3. ``Replicate()`` -> ``Shard(dim)``: 本地分块(即 ``torch.chunk``)
4. ``Partial()`` -> ``Replicate()``: ``all_reduce``
5. ``Partial()`` -> ``Shard(dim)``: ``reduce_scatter``
``redistribute`` 将正确确定 DTensors 所需的重新分配步骤
在 1-D 或 N-D DeviceMesh 上创建的。
参数:
device_mesh (:class:`DeviceMesh`, optional): 可选的 DeviceMesh,用于放置
DTensor。如果未指定,将使用当前 DTensor 的 DeviceMesh。
默认: None
placements (List[:class:`Placement`], optional): 新的放置列表(可选)
描述了如何将 DTensor 放置到 DeviceMesh 中,必须
具有与 `device_mesh.ndim` 相同的元素数量。
默认:在所有网格维度上复制
关键字参数:
async_op (bool, 可选): 是否执行 DTensor 重新分配操作
异步执行或否。默认:False
返回:
一个 `DTensor` 对象
.. note:: ``redistribute`` 可微分,这意味着用户无需担心
逆向分配操作的公式。
.. note:: ``redistribute`` 目前仅支持在同一 DeviceMesh 上重新分配 DTensor
如需将 DTensor 重新分发到不同的 DeviceMesh,请提交一个 issue。
"源代码"
# 注意:此重分发 API 目前仅支持输出
地点重新分配的数量,即它总是创建一个新的
DTensor 对象,并保留原始对象不变。
如果未指定 device_mesh,则使用当前 device_mesh
设备网状 =
设备网状
或
我.
设备网状
如果未指定新放置,则引发错误
如果
布局
是
无:
提升
运行时错误(
"需要放置来重新分配!")
布局 =
列表(
安排)
为 i,
位置
在
列举(
安排):
如果
布置.
是部分():
提升
运行时错误(
"不能重新分配到部分,重新分配到部分仅限内部使用!"
)
elif isinstance(布置,
片段)
和
布置.
维度 < 0:
将碎片维度标准化为正值
安排[i] =
片段(
布置.
维度 +
我.ndim)
布局 =
元组(
安排)
# pyre-fixme[16]: `Redistribute` has no attribute `apply`.
返回
重新分配.
应用(
我,
装置网状结构,
安排, async_op)
[文档] def 全张量(
self, *, grad_placements: Optional[Sequence[Placement]] = None
) -> torch.Tensor:
"""
返回此 DTensor 的完整张量。它将执行必要的集体操作
收集其 DeviceMesh 中其他 rank 的本地张量并连接
他们放在一起。这是以下代码的语法糖:
dtensor.redistribute(placements=[Replicate()] * mesh.ndim).to_local()
翻译为:dtensor.redistribute(放置=[Replicate()] * mesh.ndim).to_local()
关键词参数:
grad_placements (List[:class:`Placement`], optional): 放置列表(可选):放置描述
该函数返回的完整张量任何梯度布局的未来布局
函数。
`full_tensor` 将 DTensor 转换为完整的 torch.Tensor,并返回 torch.tensor
可能不会用作代码中后续复制的 DTensor 布局。这个参数是用户提供给 autograd 的提示,如果返回的张量布局与原始复制的 DTensor 布局不匹配。
如果未指定,我们将假设整个张量的梯度布局为复制。
如果返回的张量布局与原始复制的 DTensor 布局不匹配,用户可以给出这个提示给 autograd。
如果未指定,我们将假设整个张量的梯度布局为复制。
返回值:
一个表示此 DTensor 完整张量的 :class:`torch.Tensor` 对象。
.. 注意:: ``full_tensor`` 是可微分的。
"""
redist_res = self.redistribute(
placements=[Replicate()] * self.device_mesh.ndim, async_op=False
)
return _ToTorchTensor.apply(redist_res, grad_placements)
@property
def 装置网状结构(
我) ->
设备网状结构:
""
与此 DTensor 对象关联的 :class:`DeviceMesh` 属性。
注意:``device_mesh`` 是只读属性,不能设置。
"源代码"
返回
我.
规范.
网格
@property
def 安排(
我) ->
元组[
放置, ...
]
""
此 DTensor 的 placements 属性,用于描述此布局。
DTensor 在其 DeviceMesh 上的布局。
.. 注意:: ``placements`` 是只读属性,不能设置。
"源代码"
返回
我.
规范.
布局
def 创建写入条目(
我,
完全限定名:
字符串,
对象:
任意):
来自 torch.distributed.checkpoint.planner_helpers
导入 (
为 dtensor 创建写入条目,
)
如果
有属性(
我.
_本地张量,
"__创建写入条目__"):
返回
我.
_本地张量.
创建写入条目(
完全限定名,
对象)
# 类型: 忽略[attr-defined]
elif isinstance(我.
_本地张量,
火炬.
张量):
返回 [
为 dtensor 创建写入条目(
完全限定名,
对象
]
否则:
提升
运行时错误(
"不支持的张量类型!")
[文档] def __create_chunk_list__(self):
"""
返回一个包含 ChunkStorageMetadata 的列表,该数据类描述了本地分片/副本的大小/偏移量
当前排名。对于 DTensor,每个排名将只有一个本地分片/副本,因此返回的列表通常只有一个元素。
返回一个元素。
该魔术方法主要用于分布式检查点目的。
返回:
表示当前 rank 上的分片大小/偏移量的`ChunkStorageMetadata`对象列表。
"""
从`torch.distributed.checkpoint.planner_helpers`导入(
_create_chunk_from_dtensor,
)
如果 hasattr(self._local_tensor, "__create_chunk_list__"):
返回 self._local_tensor.__create_chunk_list__() # 忽略未定义的属性
elif isinstance(self._local_tensor, torch.Tensor):
返回[_从_dtensor 创建数据块](self)
else:
raise RuntimeError("不支持的张量类型!")
def 获取_tensor_shard__(
我,
索引):
如果
有属性(
我.
_本地张量,
获取张量分片):
返回
我.
_本地张量.
获取_tensor_shard__(
索引)
# 类型: 忽略[attr-defined]
elif isinstance(我.
_本地张量,
火炬.
张量):
返回
我.
本地化()
否则:
提升
运行时错误(
"不支持的张量类型!")
def 分配张量(
张量:
火炬.
张量,
装置网状结构:
可选[
设备网状结构] =
无,
安排:
可选[
序列[
安置]] =
无,
*,
src_data_rank: 可选[int] = 0,
) -> DTensor:
""
将一个叶子 `torch.Tensor`(即 nn.Parameter/buffers)分配到 `device_mesh`,按照指定的 `placements` 进行。`device_mesh` 和 `placements` 的秩必须相同。要分配的 `tensor` 是逻辑上的或“全局”张量,API 将会使用
到 `placements` 指定的地方。`device_mesh` 和 `placements` 的秩必须相同。要分配的 `tensor` 是逻辑上的或“全局”张量,API 将会使用
到 `placements` 指定的地方。`device_mesh` 和 `placements` 的秩必须相同。要分配的 `tensor` 是逻辑上的或“全局”张量,API 将会使用
设备网格维度的第一秩“tensor”作为真实来源以保留
如果您想在自动微分计算过程中构建 DTensor,请使用:meth:`DTensor.from_local`
张量(torch.Tensor):要分发的 torch.Tensor。注意,如果您
Args:
tensor (torch.Tensor):torch.Tensor 要分发。注意,如果您
想要在不是网格维度中设备数量整除的维度上分割张量
我们使用 `torch.chunk` 来对张量进行语义分割并分散碎片
不均匀分割的行为是实验性的,可能会更改
语义到碎片化张量并分散碎片。不均匀分割的行为是实验性的,可能会更改
设备网格(:class:`DeviceMesh`,可选):用于分配设备的 DeviceMesh
张量,如果未指定,必须在 DeviceMesh 上下文中调用
管理器,默认:None
放置(List[:class:`Placement`],可选):放置列表
描述如何在 DeviceMesh 上放置张量,必须与`device_mesh.ndim`的元素数量相同。
如果未指定,则默认情况下将张量复制到`device_mesh`的每个维度的第一个秩。
默认情况下,将张量复制到`device_mesh`的每个维度的第一个秩。
从`device_mesh`的第一个秩开始复制张量到每个维度的第一个秩。
关键字参数:
src_data_rank (int, optional): 源数据在逻辑/全局张量中的排名,它被用于 :meth:`distribute_tensor` 方法来将碎片/副本分散/广播到其他排名。
使用 :meth:`distribute_tensor` 方法将碎片/副本分散/广播到其他排名。
默认情况下,我们在每个 DeviceMesh 维度上使用 ``group_rank=0`` 作为源数据,以保持
单设备语义。如果显式传递 `None`,:meth:`distribute_tensor` 简单使用
使用本地数据而不是尝试通过散列/广播来保留单设备语义。
默认:0
返回:
一个 :class:`DTensor` 或 ``XLAShardedTensor`` 对象。
.. 注意::
当使用 ``xla`` 设备类型初始化 DeviceMesh 时,
返回 `XLAShardedTensor` 而不是。参见 `此问题 `__
以获取更多详细信息。XLA 集成是实验性的,可能会发生变化。
"源代码"
火炬._C._log_api_usage_once(
torch.dtensor.distribute_tensor)
# 获取默认设备网格,如果没有指定
设备网状 =
设备网状
或
_网状资源.
获取当前网状()
设备类型 =
装置网状结构.
设备类型
如果
设备类型 == "xla":
try:
# 调用 PyTorch/XLA SPMD 对 `xla` 后端类型设备网格。
# 这将返回 XLAShardedTensor
来自 torch_xla.distributed.spmd
导入 (
# type:ignore[导入]
xla_distribute_tensor,
)
返回 xla_distribute_tensor(
张量,
装置网状结构,
安排) # type:ignore[return-value]
除了
导入错误
作为 e:
msg = 使用 DTensor API 与 xla 一起使用时,您必须安装 torch_xla 包!
提升
导入错误(
信息)
来自 e
如果 not
张量.
是否为叶子节点:
提升
运行时错误(
"应使用 `distribute_tensor` 来分发叶子张量!但发现非叶子张量!"
)
如果张量不在该设备类型,则将其转换为相应的设备类型
如果
设备类型 !=
张量.
设备.
类型
和 not
张量.
是否是元数据:
张量 =
张量.
到(
设备类型)
如果没有指定,则将默认放置设置为复制
如果
布局
是
无:
布局 = [
复制()
为 _
在
范围(
装置网状结构.ndim
]
如果
长度(
安排) !=
装置网状结构.ndim:
提升 ValueError(
f"placements 的长度必须与 device_mesh.ndim 相同!"
f"找到放置长度:"{
长度(
安排)}
,以及 device_mesh.ndim:{
装置网状结构.ndim}
。
)
如果 isinstance(
张量, DTensor):
# 如果张量已经是 DTensor,我们需要检查:
# 1. 如果两个设备网格属于同一父网格且可以进行进一步分片
# 则可以进一步分片。
# 2. 检查设备网格和放置是否相同
如果
张量.
设备网状 !=
装置网状结构:
提升 ValueError(
f无法分配具有设备网格的 DTensor{
张量.
装置网状结构} "
f"传输到不同的设备网格"{
装置网状结构}
。
)
如果
张量.
布局 !=
元组(
安排):
提升 ValueError(
f"无法将具有放置的 DTensor 分配到"{
张量.
安排} "
f"不同的放置"{
安排}
.您想调用吗?
f"改为`redistribute`如何?"
)
返回
张量
本地张量 =
张量.detach()
# TODO(xilun): 解决分片顺序问题
# 按照放置位置分配张量。
布局 =
列表(
安排)
为
索引,
位置
在
列举(
安排):
如果
布置.is_shard():
位置 =
角色(
片段,
布置)
如果
布置.
维度 < 0:
标准化碎片放置维度
位置 =
片段(
布置.
维度 +
张量.ndim)
安排[
索引] =
位置
本地张量 =
布置._shard_tensor(
本地张量,
装置网状结构,
索引,
src_data_rank
源数据排名
)
elif 布置.
复制():
位置 =
角色(
复制,
布置)
本地张量 =
布置._replicate_tensor(
本地张量,
装置网状结构,
索引,
src_data_rank
源数据排名
)
否则:
提升
运行时错误(
f尝试分配具有不支持放置的张量{
布置}
在设备网格维度上{
索引}
!
)
布局 =
元组(
安排)
断言
本地张量
是 not
无,
分配张量时不应为空
# 从 DTensor 构造后断开传递给 DTensor 的本地张量
# 在 DTensor 上执行自动微分,而不是在本地张量上
规范 = DTensorSpec(
网格=
装置网状结构,
安排=
安排,
张量元=
张量元(
shape=张量.
尺寸(),
步长=
张量.
步长(),
数据类型=
张量.
数据类型,
),
)
返回 DTensor(
本地张量.
需要梯度_(
张量.
需要梯度),
规格,
需要梯度=
张量.
需要梯度,
)
@deprecated(请使用 `distribute_tensor` 并将 `src_data_rank` 设置为 `None`)
def _shard_tensor(
full_tensor: 火炬.
张量,
安排:
序列[
片段
]
装置网状结构:
可选[
设备网状结构] =
无,
) -> DTensor:
""
根据指示的分区排列在本地对整个张量进行分区
返回包含本地分片的 DTensor。
..警告:这是一个可能变更的私有 API。它跳过了
通信由 `distribute_tensor` 所需的其他通信。它仅
适用于所有等级都具有相同的 `full_tensor` 的情况。例如,
在分布式推理中,所有等级都从同一个
检查点加载。此 API 不会检查等级之间的数据相等性,因此
用户有责任确保 `full_tensor` 是相同的
分布。
参数:
full_tensor (torch.Tensor): 要分片的完整张量。
placements (Sequence[:class:`Shard`]): 描述如何在 DeviceMesh 上放置局部张量的放置方式。
描述如何在 DeviceMesh 上放置局部张量。
device_mesh (:class:`DeviceMesh`, optional): 可选的 DeviceMesh,用于放置
DTensor。必须与放置数量具有相同的维度。
如果未指定,将从中当前上下文检索。
返回:
以分片作为其局部张量的 :class:`DTensor` 对象。
示例:
>>> # xdoctest: +SKIP("需要 world_size 和 rank")
>>> device_mesh = dist.init_device_mesh("cuda", (world_size,))
>>> full_tensor = torch.arange(world_size, device=f"cuda:{rank}")
>>> dtensor = _shard_tensor(full_tensor, [Shard(1)], device_mesh)
"源代码"
返回
分配张量(full_tensor,
装置网状结构,
安排, src_data_rank=
无)
def 分布式模块(
模块: nn.
模块,
装置网状结构:
可选[
设备网状结构] =
无,
分区函数:
可选[
可调用[[
字符串, nn.
模块,
设备网状结构
]
无]] =
无,
input_fn: 可选[
可调用[[nn.
模块,
任意,
设备网状结构
]
无]] =
无,
输出函数:
可选[
可调用[[nn.
模块,
任意,
设备网状结构
]
无]] =
无,
) -> nn.模块:
""
此函数公开三个函数来控制模块的参数/输入/输出:
在运行时执行模块之前通过指定进行分片
``partition_fn``(即允许用户将模块参数转换为:class:`DTensor`)
参数根据指定的 `partition_fn` 进行划分)。
2. 在运行时执行过程中通过指定 `input_fn` 和 `output_fn` 来控制模块的输入或输出。(例如:将输入转换为 :class:`DTensor`,将输出转换回 `torch.Tensor`)
指定 `input_fn` 和 `output_fn`。 (即:将输入转换为 :class:`DTensor`,将输出转换回 `torch.Tensor`)
class:`nn.Module` 模块:要划分的用户模块。
参数:
模块 (:class:`nn.Module`):要划分的用户模块。
device_mesh (:class:`DeviceMesh`): 要放置模块的设备网格。
partition_fn (Callable): 分区参数的函数(即跨 ``device_mesh`` 分片参数)。如果未指定 ``partition_fn``,
则默认情况下,我们将 ``module`` 的所有模块参数复制到网格中。
如果 ``partition_fn`` 未指定,则默认情况下我们将 ``module`` 的所有模块参数复制到网格中。
输入函数(Callable):指定输入分布,即可以控制如何
模块的输入被分片。"input_fn" 将作为模块安装
``forward_pre_hook``(前置转发钩子)。
输出文件名(Callable):指定输出分布,即可以控制如何
输出被分片,或者将其转换回 torch.Tensor。``output_fn``将被安装为模块``forward_hook``(前向钩子)。
安装为模块``forward_hook``(前向钩子)。
返回:
包含所有参数/缓冲区都是``DTensor``的模块。
.. 注意::
当使用``xla``设备类型初始化 DeviceMesh 时,``distribute_module``。
返回带有 PyTorch/XLA SPMD 注解参数的 nn.Module。请参阅
`此问题 `__
以获取更多详细信息。XLA 集成是实验性的,可能会发生变化。
"源代码"
火炬._C._log_api_usage_once("torch.dtensor.distribute_module")
已分发 = getattr(
模块,
_已应用分发模块",
错误)
如果
已分发:
提升
运行时错误(
"分发模块应在模块上只调用一次,"
"但是这个模块已经被调用了!"
)
设备网状 =
设备网状
或
_网状资源.
获取当前网状()
设备类型 =
装置网状结构.
设备类型
如果
设备类型 == "xla":
try:
# 这个函数用于为自动分区标注所有模块参数
# PyTorch/XLA SPMD 或显式分区到 :class:`XLAShardedTensor` 参数
# 根据 `partition_fn` 指定的进行分区。
来自 torch_xla.distributed.spmd
导入 (
# type:ignore[导入]
xla_distribute_module,
)
返回 xla_distribute_module(
模块,
装置网状结构,
分区函数, input_fn,
输出函数
) # type:ignore[return-value]
除了
导入错误
作为 e:
msg = 使用 DTensor API 与 xla 一起使用时,您必须安装 torch_xla 包!
提升
导入错误(
信息)
来自 e
def 复制模块参数缓冲区(m: nn.
模块,
网格:
设备网状结构) ->
无:
此函数遍历直接模块参数
将所有非 DTensor 参数/缓冲区复制到 DTensor
# 参数/缓冲区,如果它们尚未分区
# partition_fn,我们在这里不能轻易使用 `module._apply`
# 因为不知道 partition_fn 内部发生了什么
用户可以做任何事情,例如安装钩子,我们希望
保留这些。
完整复制 = [
复制()] *
网格.
维数
为
键,
参数
在 m.
参数.
项目():
如果
参数
是 not
无
和 not isinstance(
参数, DTensor):
m.注册参数(
键,
nn.参数(
分配张量(
参数.
数据,
网格,
完全复制)),
)
为
键,
缓冲区
在 m.
_缓冲区.
项目():
如果
缓冲区
是 not
无
和 not isinstance(
缓冲区, DTensor):
m._缓冲区[
键] =
分配张量(
缓冲区,
网格,
完全复制)
如果
分区函数
是
无:
# 如果未指定分区函数,则默认复制
所有模块的参数/缓冲区
为
名称,
子模块
在
模块.
命名模块():
复制模块参数缓冲区(
子模块,
装置网状结构)
否则:
将 partition_fun 应用到子模块
为
名称,
子模块
在
模块.
命名模块():
分区函数(
名称,
子模块,
装置网状结构)
复制模块参数缓冲区(
子模块,
装置网状结构)
# 将输入函数注册为模块前向预钩子
如果
输入函数
是 not
无:
# 检查输入函数的签名
参数数量 =
长度(
检查.
签名(input_fn).
参数)
如果
参数数量 == 2:
# 输入函数仅接受输入和设备网格
warnings.警告(
"弃用接受两个参数(inputs, device_mesh)的 input_fn,"
"请使用接受(module, inputs, device_mesh)的 input_fn 代替!",
未来警告,
栈级别=2,
)
模块.
注册前向钩子(
lambda _, 输入: input_fn(
输入,
装置网状结构)
忽略调用参数
)
elif 参数数量 == 3:
输入_fn 接收模块、输入和设备网格
模块.
注册前向钩子(
lambda 模块,
输入: input_fn(
模块,
输入,
装置网状结构)
)
否则:
提升 ValueError(
f"input_fn 应该接受 3 个参数,但得到了 "{
参数数量}
个参数!
)
# 将 output_fn 注册为模块前向钩子
如果
输出函数
是 not
无:
参数数量 =
长度(
检查.
签名(
输出函数).
参数)
如果
参数数量 == 2:
输出文件名只接受输出和设备网格
warnings.警告(
"弃用接受两个参数(inputs, device_mesh)的 output_fn,"
"请使用接受(module, inputs, device_mesh)的 output_fn 代替!",
未来警告,
栈级别=2,
)
模块.
注册前向钩子(
lambda 模块,
输入,
输出:
输出函数(
输出,
装置网状结构)
忽略调用参数
)
elif 参数数量 == 3:
模块.
注册前向钩子(
lambda 模块,
输入,
输出:
输出函数(
模块,
输出,
装置网状结构)
)
否则:
提升 ValueError(
f"output_fn 应该接受 3 个参数,但得到了 "{
参数数量}
个参数!
)
模块._distribute_module_applied =
真实
# 类型:忽略[赋值]
返回
模块
以下为张量工厂函数 API,用于直接创建 DTensor。我们需要
将工厂函数 API 分开,因为张量子类无法重写张量
工厂方法,我们需要用户使用用户意图的 device_mesh
和放置来创建合适的 DTensor。
def _dtensor_init_helper( # 类型:忽略[未指定类型定义]
初始化操作,
尺寸:
火炬.
尺寸,
装置网状结构:
可选[
设备网状结构] =
无,
安排:
可选[
序列[
放置]] =
无,
**kwargs,
) -> DTensor:
# from torch.distributed._tensor.placement_types import DTensorSpec, TensorMeta
# 如果 device_mesh 为空,则使用 mesh 资源中的那个
设备网状 =
设备网状
或
_网状资源.
获取当前网状()
kwargs["设备"] =
装置网状结构.
设备类型
如果没有指定,则将默认放置设置为复制
布局 =
布局
或
元组(
复制()
为 _
在
范围(
装置网状结构.ndim))
检查设备网格与放置项
断言
装置网状结构.
维数 ==
长度(
安排), (
"网格尺寸与放置长度不匹配"
)
断言 kwargs[
布局] ==
火炬.strided,
"布局值不受支持!"
火炬步长 =
火炬._prims_common.
使步长连续(
尺寸)
# 获取局部张量形状
本地形状, _ =
计算局部形状和全局偏移(
尺寸,
装置网状结构,
布局
)
# 初始化局部张量
如果
初始化操作 ==
火炬.full:
填充值 = kwargs.
弹出(
填充值, 0)
本地张量 =
初始化操作(
本地形状,
填充值, **kwargs)
elif 初始化操作 ==
火炬.
随机
或
初始化操作 ==
火炬.randn:
此张量元数据除了 `shape` 之外不使用
dtype = kwargs.获取("dtype",
火炬.
获取默认数据类型())
张量元数据 =
张量元(
尺寸, (0,),
数据类型)
规范 = DTensorSpec(
装置网状结构,
元组(
安排),
张量元=
张量元)
如果
随机.
是否支持随机网格(
装置网状结构)
和 not
随机._rng_tracker:
随机._rng_tracker =
随机.
基于偏移的 RNG 追踪器(
装置网状结构)
断言
随机._rng_tracker
是 not
无
与
随机._rng_tracker._distribute_region(
规格):
本地张量 =
初始化操作(
本地形状, **kwargs)
否则:
本地张量 =
初始化操作(
本地形状, **kwargs)
规范 = DTensorSpec(
装置网状结构,
元组(
安排),
张量元=
张量元(
尺寸,
torch_stride,
本地张量.
数据类型,
),
)
返回 DTensor(
本地张量,
规格,
需要梯度=kwargs[
requires_grad
]
)
def 一(
# 类型:忽略[未指定类型定义]
*尺寸,
数据类型:
可选[
火炬.
数据类型] =
无,
布局:
火炬.
布局 =
火炬.strided,
需要梯度:
布尔类型 =
错误,
装置网状结构:
可选[
设备网状结构] =
无,
安排:
可选[
序列[
放置]] =
无,
) -> DTensor:
""
返回一个填充了标量值 1 的 :class:`DTensor`,其形状由变量参数 `size` 定义。
`size` (int...): 定义输出 :class:`DTensor` 形状的整数序列。
参数:
size (int...): 定义输出 :class:`DTensor` 形状的整数序列。
可以是可变数量的参数或类似列表或元组的集合。
例如:ones(1,2,3..) 或 ones([1,2,3..]) 或 ones((1,2,3..))
关键字参数:
dtype (:class:`torch.dtype`,可选):返回 :class:`DTensor` 的期望数据类型。
默认:如果为 ``None``,则使用全局默认值(见 :func:`torch.set_default_dtype`)。
返回的 DTensor 的期望布局 (:class:`torch.layout`,可选):
默认:``torch.strided``。
requires_grad (bool,可选):如果 autograd 应记录操作。
返回 :class:`DTensor`。默认: ``False``。
device_mesh::class:`DeviceMesh` 类型,包含 ranks 的网格信息
放置序列::class:`Placement` 类型:``Shard``,``Replicate``
返回:
每个 rank 上的 :class:`DTensor` 对象
"源代码"
torch_size = 标准化到 torch 大小(
尺寸)
返回 _dtensor_init_helper(
火炬.
一,
torch_size,
数据类型=
数据类型,
布局=
布局,
需要梯度=
需要梯度,
装置网状结构=
装置网状结构,
安排=
安排,
)
def 空的(
# 类型:忽略[未指定类型定义]
*尺寸,
数据类型:
可选[
火炬.
数据类型] =
无,
布局:
火炬.
布局 =
火炬.strided,
需要梯度:
布尔类型 =
错误,
装置网状结构:
可选[
设备网状结构] =
无,
安排:
可选[
序列[
放置]] =
无,
) -> DTensor:
""
返回一个填充未初始化数据的 :class:`DTensor`。
其形状由变量参数 `size` 定义。
参数:
size (int...): 定义输出 :class:`DTensor` 形状的整数序列。
可以是可变数量的参数或类似列表或元组的集合。
例如:empty(1,2,3..) 或 empty([1,2,3..]) 或 empty((1,2,3..))
关键字参数:
dtype (:class:`torch.dtype`,可选):返回 :class:`DTensor` 的期望数据类型。
默认:如果为 ``None``,则使用全局默认值(见 :func:`torch.set_default_dtype`)。
layout (:class:`torch.layout`,可选):返回 :class:`DTensor` 的期望布局。
默认:``torch.strided``。
requires_grad (bool,可选):如果 autograd 应记录操作。
返回 :class:`DTensor`。默认: ``False``。
device_mesh::class:`DeviceMesh` 类型,包含 ranks 的网格信息
放置序列::class:`Placement` 类型:``Shard``,``Replicate``
返回:
每个 rank 上的 :class:`DTensor` 对象
"源代码"
torch_size = 标准化到 torch 大小(
尺寸)
返回 _dtensor_init_helper(
火炬.
空的,
torch_size,
数据类型=
数据类型,
布局=
布局,
需要梯度=
需要梯度,
装置网状结构=
装置网状结构,
安排=
安排,
)
def full( # 类型:忽略[未指定类型定义]
尺寸,
填充值,
*,
数据类型:
可选[
火炬.
数据类型] =
无,
布局:
火炬.
布局 =
火炬.strided,
需要梯度:
布尔类型 =
错误,
装置网状结构:
可选[
设备网状结构] =
无,
安排:
可选[
序列[
放置]] =
无,
) -> DTensor:
""
返回一个根据 `device_mesh` 和 `placements` 填充 `fill_value` 的 `:class:`DTensor`。
其形状由参数 `size` 定义。
参数:
size (int...): 定义输出 :class:`DTensor` 形状的整数序列。
可以是可变数量的参数或类似列表或元组的集合。
例如:ones(1,2,3..) 或 ones([1,2,3..]) 或 ones((1,2,3..))
fill_value(标量):用于填充输出张量的值。
关键字参数:
dtype (:class:`torch.dtype`,可选):返回 :class:`DTensor` 的期望数据类型。
默认:如果为 ``None``,则使用全局默认值(见 :func:`torch.set_default_dtype`)。
返回的 DTensor 的期望布局 (:class:`torch.layout`,可选):
默认:``torch.strided``。
requires_grad (bool,可选):如果 autograd 应记录操作。
返回 :class:`DTensor`。默认: ``False``。
device_mesh: :class:`DeviceMesh` 类型,包含 ranks 的网格信息。
放置序列::class:`Placement` 类型:``Shard``,``Replicate``
返回:
每个 rank 上的 :class:`DTensor` 对象
"源代码"
torch_size = 标准化到 torch 大小(
尺寸)
返回 _dtensor_init_helper(
火炬.full,
torch_size,
填充值=
填充值,
数据类型=
数据类型,
布局=
布局,
需要梯度=
需要梯度,
装置网状结构=
装置网状结构,
安排=
安排,
)
def 随机(
# 类型:忽略[未指定类型定义]
*尺寸,
需要梯度:
布尔类型 =
错误,
数据类型:
可选[
火炬.
数据类型] =
无,
布局:
火炬.
布局 =
火炬.strided,
装置网状结构:
可选[
设备网状结构] =
无,
安排:
可选[
序列[
放置]] =
无,
) -> DTensor:
""
返回一个填充有均匀分布随机数的 :class:`DTensor`
的区间 ``[0, 1)``。张量的形状由变量 ``size`` 定义。
size(int...):定义输出 :class:`DTensor` 形状的整数序列。
参数:
size (int...): 定义输出 :class:`DTensor` 形状的整数序列。
可以是可变数量的参数或类似列表或元组的集合。
例如:ones(1,2,3..) 或 ones([1,2,3..]) 或 ones((1,2,3..))
关键字参数:
dtype (:class:`torch.dtype`,可选):返回 :class:`DTensor` 的期望数据类型。
默认:如果为 ``None``,则使用全局默认值(见 :func:`torch.set_default_dtype`)。
返回的 DTensor 的期望布局 (:class:`torch.layout`,可选):
默认:``torch.strided``。
requires_grad (bool,可选):如果 autograd 应记录操作。
返回 :class:`DTensor`。默认: ``False``。
device_mesh: :class:`DeviceMesh` 类型,包含 ranks 的网格信息。
放置序列::class:`Placement` 类型:``Shard``,``Replicate``
返回:
每个 rank 上的 :class:`DTensor` 对象
"源代码"
torch_size = 标准化到 torch 大小(
尺寸)
返回 _dtensor_init_helper(
火炬.
随机,
torch_size,
数据类型=
数据类型,
布局=
布局,
需要梯度=
需要梯度,
装置网状结构=
装置网状结构,
安排=
安排,
)
def randn( # 类型:忽略[未指定类型定义]
*尺寸,
需要梯度:
布尔类型 =
错误,
数据类型:
可选[
火炬.
数据类型] =
无,
布局:
火炬.
布局 =
火炬.strided,
装置网状结构:
可选[
设备网状结构] =
无,
安排:
可选[
序列[
放置]] =
无,
) -> DTensor:
""
返回一个填充有正态分布随机数的 :class:`DTensor`
均值为 0,方差为 1。张量的形状由变量
size(int...):定义输出 :class:`DTensor` 形状的整数序列。
参数:
size (int...): 定义输出 :class:`DTensor` 形状的整数序列。
可以是可变数量的参数或类似列表或元组的集合。
例如:ones(1,2,3..) 或 ones([1,2,3..]) 或 ones((1,2,3..))
关键字参数:
dtype (:class:`torch.dtype`,可选):返回 :class:`DTensor` 的期望数据类型。
默认:如果为 ``None``,则使用全局默认值(见 :func:`torch.set_default_dtype`)。
返回的 DTensor 的期望布局 (:class:`torch.layout`,可选):
默认:``torch.strided``。
requires_grad (bool,可选):如果 autograd 应记录操作。
返回 :class:`DTensor`。默认: ``False``。
device_mesh: :class:`DeviceMesh` 类型,包含 ranks 的网格信息。
放置序列::class:`Placement` 类型:``Shard``,``Replicate``
返回:
每个 rank 上的 :class:`DTensor` 对象
"源代码"
torch_size = 标准化到 torch 大小(
尺寸)
返回 _dtensor_init_helper(
火炬.randn,
torch_size,
数据类型=
数据类型,
布局=
布局,
需要梯度=
需要梯度,
装置网状结构=
装置网状结构,
安排=
安排,
)
def 零(
# 类型:忽略[未指定类型定义]
*尺寸,
需要梯度:
布尔类型 =
错误,
数据类型:
可选[
火炬.
数据类型] =
无,
布局:
火炬.
布局 =
火炬.strided,
装置网状结构:
可选[
设备网状结构] =
无,
安排:
可选[
序列[
放置]] =
无,
) -> DTensor:
""
返回一个填充了标量值 0 的 :class:`DTensor`。
参数:
size (int...): 定义输出 :class:`DTensor` 形状的整数序列。
可以是可变数量的参数或类似列表或元组的集合。
例如:zeros(1,2,3..) 或 zeros([1,2,3..]) 或 zeros((1,2,3..))。
关键字参数:
requires_grad (bool,可选):如果 autograd 应记录操作。
返回 :class:`DTensor`。默认: ``False``。
dtype (:class:`torch.dtype`,可选):返回 :class:`DTensor` 的期望数据类型。
默认:如果为 ``None``,则使用全局默认值(见 :func:`torch.set_default_dtype`)。
layout (:class:`torch.layout`,可选):返回 :class:`DTensor` 的期望布局。
默认:``torch.strided``。
device_mesh::class:`DeviceMesh` 类型,包含 ranks 的网格信息
放置序列::class:`Placement` 类型:``Shard``,``Replicate``
返回:
每个 rank 上的 :class:`DTensor` 对象
"源代码"
torch_size = 标准化到 torch 大小(
尺寸)
返回 _dtensor_init_helper(
火炬.
零,
torch_size,
数据类型=
数据类型,
布局=
布局,
需要梯度=
需要梯度,
装置网状结构=
装置网状结构,
安排=
安排,
)