已关闭
【RFC】hyper_parallel增加三种placement,Shard,Replicate,Partial #7
yide12创建于  1月14日关闭于  3月4日
yide12
yide12成员
1月14日 创建
name about labels
RFC Use this template for requirement to be discussed kind/feature or kind/enhancement
Requirement Use this template for Confirmed requirements kind/feature or kind/enhancement

Backgroud(背景信息)

  • Describe/Explain the status of the problem you wish to solve.
  • Attach relevant issues if there is any.

目前在分布式并行逻辑中,用户通常需要通过复杂的 tensor_map(整型元组)来手动配置张量的切分策略。这种方式对用户不够直观,且难以表达复杂的混合并行策略(如 Partial 规约状态)。为了提升分布式编程的可读性和易用性,需要引入一套高层抽象的放置策略(Placement)体系,并实现其与底层执行算子所需的 tensor_map 之间的自动转换。

Origin(信息来源)

  • Explain which department/team made this request so that its priority can be given.

该需求由hyper_parallel提出,旨在统一分布式张量布局的表达方式。

Benefit / Necessity (价值/作用)

  • Describe/Explain the key value by fulfilling the request.

  • 提升易用性:用户可以使用 Shard、Replicate、Partial 等语义化对象配置并行策略,而非晦涩的数字索引。

  • 增强表达能力:明确区分了分片(Shard)、复制(Replicate)和待规约(Partial)状态,支持更精细的算子并行控制。

  • 无缝兼容:通过双向转换机制,既能保留高层语义,又能兼容底层现有的并行调度逻辑。

Design(设计方案)

  • Describe/Explain the general idea of the design. Pseudo-code is allowed

Tensor_map 与 Placement

device_mesh是设备矩阵,用于表示设备的分布。
为了表示tensor如何在device_mesh上切分的,有两种表示方式。

  1. tensor_map从tensor角度,描述的是Tensor的每个维度在device_mesh上的分布。
  2. placement从设备矩阵角度,描述的是device_mesh上的分布策略。

Placement简介

Placement定义了设备矩阵的切分分布。hyper_parallel对标torch提供了三种分布策略:Shard、Replicate 和 Partial。

  • Shard: 表示张量沿着特定的维度被切分到不同的设备上。
  • Replicate: 表示张量在所有相关设备上保留完整的副本。
  • Partial: 表示张量在设备上处于“部分计算结果”状态,通常需要通过规约(比如:sum、max、min、avg)操作来同步。

torch中,placement会根据相应的策略切分Tensor;hyper_parallel中已经实现了tensor切分逻辑,placement只记录切分的策略,通过将placement转成原有的tensor_map接入框架。

# 描述同一种分布
from hyper_parallel.core.device_mesh import DeviceMesh
device_mesh = DeviceMesh((2, 2), ("dp", "tp"))
tensor = mindspore.randn((3, 4, 5)) # 3维张量
placements = [Shard(0), Shard(1)] # 表示设备矩阵的第0轴对张量维0进行切分,第1轴对张量维1进行切分。
t_map = (1, 0, -1) # 表示张量维0由网格高维切分,维1由网格低维切分。

可以看出,tensor_map的长度是tensor的dim,placement的长度是device_mesh的dim。

hyper_parallel 中 Tensor_map 与 Placement 之间的相互转换

在Hyper_Parallel 中,Placement 与 Tensor_map 之间的转换是通过 Layout 实现的。

从 Placement 到 Tensor Map

通过 placement_to_tensor_map(dim) 方法实现:

  1. 映射关系: 遍历 placements 列表。
  2. Shard 处理: 将 Shard(i) 中的维度 i 映射到对应的设备轴索引。
  3. Partial 处理: 如果检测到 Partial,则在 Layout 的 partial 状态中记录对应的规约操作(如 sum)。
  4. 索引倒置: 内部使用 device_dim_count - 1 - mesh_idx 的逻辑来匹配底层集群的分片习惯。

由于placement不包含Tensor维度信息,所以转换的时候需要传入tensor的dim。

从 Tensor Map 到 Placement

通过 tensor_map_to_placement() 方法实现逆向转换:

  • 根据 tensor_map 中的索引值还原出 Shard 对象。
  • 若 tensor_map 值为 -1 且无 Partial 状态,则还原为 Replicate。
  • 若对应轴存在规约操作,则还原为 Partial。

代码示例

from hyper_parallel.core.layout import Layout
from hyper_parallel.core.placement_types import Shard, Replicate, Partial
from hyper_parallel.core.device_mesh import DeviceMesh
device_mesh = DeviceMesh((2, 2), ("dp", "tp"))
layout = Layout.from_device_mesh(device_mesh) # layout = Layout((2, 2), ("dp", "tp"))

layout([Shard(0), Shard(1)]) # 传入tensor_map, layout((1, 0, -1))

# 从placement 转换为 tensor_map
t_map = layout.placement_to_tensor_map(dim=3)

# 从 tensor_map 转换为 placement
placement = layout.tensor_map_to_placement()

相关接口变化

引入placement之后,为了接口统一和易用性,原有的layout接口不再使用,统一使用device_mesh+placement。

框架内部,通过将device_mesh+placement转换成已有layout,从而接入已有的并行能力。

# 相关接口变化

from hyper_parallel.core.dtensor import DTensor

# 创建dtensor
DTensor.from_local(local_tensor, layout)
# 变为
DTensor.from_local(local_tensor, device_mesh, placements)
DTensor(local_tensor, device_mesh, placements)

# 重排布
DTensor.redistribute(self, dst_layout)
# 变为
DTensor.redistribute(self, device_mesh, placements)

# 自定义切分
custom_shard(func, out_layouts, in_layouts)
# 变为
custom_shard(func, device_mesh, out_placements, in_placements)

# tp并行
sharding_plan = {
“parameter”: {“mlp.weight”: layout(“None”, “tp”)}
“forward”: {“input”: layout(“dp”, “None”),
“output”:layout(“dp”, “tp”)}}
shard(model, sharding_plan)
# 变为
sharding_plan = {
“parameter”: {“mlp.weight”: (Replicate(), Shard(1))}
“forward”: {“input”: (Shard(0), Replicate()),
“output”:(Shard(0), Shard(1))}}
shard(model, sharding_plan)
likedislike
yide12yide12成员
1月14日 创建了RFC
yide12yide12成员
1月14日 修改了描述
yide12yide12成员
1月14日 修改了描述
yide12yide12成员
1月14日 关联了MindSpore/hyper-parallel Pull Request !64
yide12yide12成员
1月14日 修改了描述
yide12yide12成员
1月26日 修改标题为 “【RFC】hyper_parallel增加三种placement,Shard,Replicate,Partial”,原标题为“hyper_parallel增加三种placement,Shard,Replicate,Partial”
yide12yide12成员
2月25日 issue状态由 TODO 改变为 DONE
yide12yide12成员
2月25日 关闭了 issue
MindSpore-Bot
MindSpore-Bot成员
2月25日 评论:

Notice

@yide12 , you can't close an issue unless the issue has link pull requests.

likedislike
MindSpore-BotMindSpore-Bot成员
2月25日 issue状态由 DONE 改变为 TODO
MindSpore-BotMindSpore-Bot成员
2月25日 重新打开了 issue
yide12
yide12成员
3月4日 评论:
yide12yide12成员
3月4日 issue状态由 TODO 改变为 DONE
yide12yide12成员
3月4日 关闭了 issue
MindSpore-Bot
MindSpore-Bot成员
3月4日 评论:

Notice

@yide12 , you can't close an issue unless the issue has link pull requests.

likedislike
MindSpore-BotMindSpore-Bot成员
3月4日 issue状态由 DONE 改变为 TODO
MindSpore-BotMindSpore-Bot成员
3月4日 重新打开了 issue
yide12yide12成员
3月4日 issue状态由 TODO 改变为 DONE
yide12yide12成员
3月4日 关闭了 issue