已关闭
【RFC】hyper_parallel增加三种placement,Shard,Replicate,Partial #7
yide12创建于 1月14日关闭于 3月4日
1月14日 创建了RFC
1月14日 修改了描述
1月14日 修改了描述
1月14日 关联了MindSpore/hyper-parallel Pull Request !64
1月14日 修改了描述
1月26日 修改标题为 “【RFC】hyper_parallel增加三种placement,Shard,Replicate,Partial”,原标题为“hyper_parallel增加三种placement,Shard,Replicate,Partial”
1月26日 修改标题为 “【RFC】hyper_parallel增加三种placement,Shard,Replicate,Partial”,原标题为“hyper_parallel增加三种placement,Shard,Replicate,Partial”
2月25日 issue状态由 TODO 改变为 DONE
2月25日 关闭了 issue
MindSpore-Bot
2月25日 评论:
2月25日 评论:
Notice
@yide12 , you can't close an issue unless the issue has link pull requests.


2月25日 issue状态由 DONE 改变为 TODO
2月25日 重新打开了 issue
yide12
3月4日 评论:
3月4日 评论:
3月4日 issue状态由 TODO 改变为 DONE
3月4日 关闭了 issue
MindSpore-Bot
3月4日 评论:
3月4日 评论:
Notice
@yide12 , you can't close an issue unless the issue has link pull requests.


3月4日 issue状态由 DONE 改变为 TODO
3月4日 重新打开了 issue
3月4日 issue状态由 TODO 改变为 DONE
3月4日 关闭了 issue
Backgroud(背景信息)
目前在分布式并行逻辑中,用户通常需要通过复杂的 tensor_map(整型元组)来手动配置张量的切分策略。这种方式对用户不够直观,且难以表达复杂的混合并行策略(如 Partial 规约状态)。为了提升分布式编程的可读性和易用性,需要引入一套高层抽象的放置策略(Placement)体系,并实现其与底层执行算子所需的 tensor_map 之间的自动转换。
Origin(信息来源)
该需求由hyper_parallel提出,旨在统一分布式张量布局的表达方式。
Benefit / Necessity (价值/作用)
Describe/Explain the key value by fulfilling the request.
提升易用性:用户可以使用 Shard、Replicate、Partial 等语义化对象配置并行策略,而非晦涩的数字索引。
增强表达能力:明确区分了分片(Shard)、复制(Replicate)和待规约(Partial)状态,支持更精细的算子并行控制。
无缝兼容:通过双向转换机制,既能保留高层语义,又能兼容底层现有的并行调度逻辑。
Design(设计方案)
Tensor_map 与 Placement
device_mesh是设备矩阵,用于表示设备的分布。
为了表示tensor如何在device_mesh上切分的,有两种表示方式。
Placement简介
Placement定义了设备矩阵的切分分布。hyper_parallel对标torch提供了三种分布策略:
Shard、Replicate和Partial。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)方法实现:placements列表。Shard(i)中的维度i映射到对应的设备轴索引。Partial,则在Layout的partial状态中记录对应的规约操作(如sum)。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)