静态 Shape 多流并行增强:让图中的任务真正并行
## 引言
在大模型训练、推理和推荐网络中,计算图里经常同时存在重复模块、独立分支,以及运行在不同硬件单元上的算子。当输入 Shape 可以提前确定时,完整模型或其中一部分可以形成静态 DAG,在编译阶段完成图优化和执行编排,再下沉到 Device 侧执行。
静态图减少了运行时逐算子调度的开销,但整图下沉并不代表整图已经并行。单 Stream 会把所有任务排成一队:一个 AIC 算子和一个 AIV 算子即使没有依赖,也可能只能前后执行;两个无依赖的 AIC 算子即使没有用满硬件资源,也仍然要排队。
结果就是,一部分硬件在工作,另一部分硬件在等待;或者同一类硬件还有余量,却没有更多任务同时进入。
静态 Shape 多流并行增强模块就是为了解决这个问题。它从完整计算图中寻找并行机会,把任务重新编排到多条 Stream 上,再通过 Profiling 和硬件资源约束修正排布,让“图上可以并行”真正变成“硬件上能够有效并行”。当前模块集成在 GE 的图优化流程中。
一、多流优化方法
1.1 先看任务能不能重叠,再决定要不要拆流
多流不是简单增加几条 Stream。图中存在无依赖分支,只能说明这些任务在逻辑上可以同时推进;是否值得拆开,还要看任务耗时、同步成本和硬件资源。
为什么要做这层判断?原因很直接:如果分支任务很短,新增的 Event Record/Wait 可能比并行收益还大;如果几条流同时争用已经饱和的 AIC 或 AIV 资源,表面上是多流,硬件时间线上仍然接近串行。
因此,多流优化需要计算的是一笔总账:
多流净收益 = 任务重叠收益 - 同步开销 - 管理开销 - 资源竞争
只有重叠收益能够覆盖新增成本,拆流才有意义。
1.2 多流优化不是一个动作,而是一个闭环
完整的多流优化可以概括为“拆 → 合 → 测 → 改”:
静态 DAG
↓
拆:找出可以独立推进的逻辑路径
↓
合:生成固定流数下的物理流候选
↓
测:通过 Profiling 获取真实耗时和资源信息
↓
改:调整资源冲突和无效并发
↓
Device 实测:选择端到端更快的方案
这里的目标不是得到最多的 Stream,而是得到更短的端到端执行时间。流数增加但性能不变,甚至出现回退,都说明新增的流没有转化为有效并行。
1.3 三条原则,贯穿整个过程
| 原则 | 说明 |
|---|---|
| 依赖正确 | 原始依赖不能丢,跨流 Event 必须完整,最终执行图不能形成环 |
| 并发有效 | 辅流要产生真实任务重叠,不能大部分时间都在等待 |
| 资源可承载 | 同一时间窗口内的 AIC/AIV 需求不能超过硬件上限 |
正确性是前提,有效并发是目标,硬件资源是边界。三者缺一不可。
二、多流模块如何完成调度
2.1 逻辑流拆解:先把可以并行的路径找出来
多流调度的第一步,是从 DAG 中找到能够独立推进的路径。这里得到的是逻辑流,它描述计算图中的路径覆盖,并不等同于最终创建的 Device Stream。
以下图为例,主链 A→B→E→H 与 C、D 两个分支共同组成一张静态 DAG:

多流模块会综合图拓扑、算子执行引擎、资源需求和互斥约束,识别可以连续执行的节点。实现上可以使用二分图最大匹配等路径覆盖方法,得到类似下面的结果:
L1:A → B → E → H
L2:C → F
L3:D → G
这里的 M=3,表示覆盖全部节点需要 3 条逻辑流。简单来说,M 描述的是“覆盖全图需要多少条逻辑路径”,并不代表最终一定要创建 3 条真实 Stream。
2.2 物理流合并:Stream 不是越多越好
找到 M 条逻辑流之后,下一步是把它们合并成 K 条物理流。物理流才是 Device 上真正承载任务的 Stream。
为什么还要再合并?因为逻辑路径拆得开,不代表每条路径都值得占用一条 Stream。流数过多会增加 Event、内存和管理开销,也可能产生长期空闲的无效辅流。
固定候选流数 K 后,多流模块会从三类思路生成候选排布:
| 策略 | 核心思路 |
|---|---|
| 用户指定 | 保留用户明确指定的流归属 |
| 负载均衡 | 让各物理流上的任务量尽量接近 |
| 主流优先 | 优先填充主流空闲窗口,确有需要时再使用辅流 |
三种策略解决的是“任务怎么合并”,共同底线是不破坏原始依赖。生成候选后,还要检查 Event 是否必要、辅流是否有真实重叠,以及跨流依赖与流内顺序叠加后是否仍然无环。
通过这一轮筛选,模块输出的是固定 K 下正确且具备并行价值的物理流候选,而不是简单把 M 条逻辑流平均分组。
2.3 加权控核:图上能并,不代表硬件能跑
前两步主要依赖图结构和算子基础属性。第一次执行前,调度器还不知道每个算子的真实耗时。两条算子数量相同的逻辑流,实际负载可能完全不同。
首轮执行完成后,Profiling 会把算子的真实完成时间归一化为调度权重:
调度权重 = Normalize(算子真实完成时间)
有了时间信息,还要检查任务重叠时的硬件资源:
Σ AIC 需求 ≤ AIC 可用总量
Σ AIV 需求 ≤ AIV 可用总量
如果某个时间窗口内的资源需求超过硬件上限,模块会在依赖允许的范围内调整任务位置;如果调整后某条辅流仍然没有真实重叠价值,就把它合并回其他流。
这一步可以概括为一句话:用真实耗时判断负载,用硬件上限约束并发。它不是继续增加 Stream,而是把逻辑多流修正为硬件真正能够承载的物理多流。
对于固定 K,物理流合并和加权控核会共同生成更合理的候选;不同 K 之间,再通过 Device 端到端实测选出更优方案。
三、性能测试与收益分析
性能验证分为两个阶段。第一次执行没有历史 Profiling,主要验证图结构驱动的基础多流;获得真实耗时后,再验证加权控核带来的增量收益。
【测试环境】
硬件型号:Ascend 910系列、Ascend 950系列;CANN版本:9.1.0;
性能指标:模型端到端耗时;预热次数:10;重复测试次数:100。
3.1 第一次执行:基础多流能带来多少收益
第一次执行只使用逻辑流拆解和物理流合并,不依赖历史 Profiling。测试时以单 Stream 为 Baseline,对比基础多流的端到端时延:
Speedup = 单流时延 / 基础多流时延
| Case名称 | 单流Baseline | 基础多流 | Speedup |
|---|---|---|---|
| 网络典型场景1 | 713 us | 484 us | 32.12% |
| 网络典型场景2 | 1577 us | 963 us | 39.83% |
| 网络典型场景3 | 3311 us | 2170 us | 34.46% |

基础多流的收益来自独立任务重叠,并没有减少算子本身的计算量。因此,图并行空间越充分、分支任务越长,越容易看到收益;如果同步开销较高或硬件本身已经饱和,收益可能较小。
3.2 获得 Profiling 后:加权控核还能带来多少增量
首轮 Profiling 给出了真实负载和资源占用信息。在相同输入、硬件和统计口径下,对比基础多流与加权控核增强多流:
| Case名称 | 基础多流 | 加权控核增强多流 | 加权控核增量 |
|---|---|---|---|
| 网络典型场景1 | 484 us | 352 us | 18.51% |
| 网络典型场景2 | 963 us | 805 us | 10.02% |
| 网络典型场景3 | 2170 us | 1904 us | 8.03% |

如果基础排布中存在明显的负载失衡或资源冲突,加权控核通常更容易获得增量;如果基础排布已经比较合理,增量较小也是符合预期的结果。
3.3 从 Profiling 看收益来自哪里
性能数据回答“快了多少”,Profiling 则回答“为什么会快”。对比单流、基础多流和加权控核结果时,建议统一时间尺度,重点观察三件事:
- 原本排队的独立任务是否真正发生重叠;
- Event 和 Wait 区间是否得到控制;
- AIC/AIV 是否从资源超限竞争变为资源合法并行。

理想的 Profiling 结果不是 Stream 数量更多,而是关键路径更短、有效重叠更多、等待和资源冲突更少。
四、多流调优 Checklist
在实际测试过程中,可以按下面的清单逐项检查:
- 固定硬件、输入和统计方法,建立单流 Baseline;
- 确认图中存在值得重叠的无依赖路径;
- 检查跨流 Event 是否必要且完整;
- 确认辅流产生了真实重叠,而不是长期等待;
- 检查每个并发窗口的 AIC/AIV 需求是否超过上限;
- 使用 Profiling 定位负载失衡、资源冲突和关键路径;
- 比较不同 K 的 Device 端到端结果,不用流数代替性能结论;
- 保留无收益或性能回退的场景,并分析具体原因。
五、常见问题
| 现象 | 可能原因 | 建议 |
|---|---|---|
| Stream 增加但性能不变 | 图并行空间有限,或者辅流长期等待 | 查看关键路径和有效重叠窗口 |
| 启用多流后性能回退 | 同步和管理开销超过重叠收益 | 对比 Wait 区间和端到端时延 |
| 图上已经并行,硬件仍在排队 | 同类资源需求超过硬件上限 | 查看 AIC/AIV Resource Timeline |
| 加权控核增量较小 | 基础多流排布已经比较合理 | 确认是否仍存在资源冲突或负载失衡 |
| 执行无法继续推进 | 流内顺序和跨流依赖形成环 | 检查 Event 完整性和执行图无环性 |
结语
静态 Shape 多流并行增强模块并不追求更多 Stream,而是追求更多有效并行。
逻辑流拆解负责找到图中的并行空间,物理流合并负责生成可执行的多流候选,Profiling 和硬件资源约束负责把逻辑并行修正为硬件可承载的真实重叠,最后再通过 Device 实测选择端到端更优的方案。
判断多流优化是否有效,最终只需要回到三个问题:任务是否真正重叠,资源是否能够承载,以及端到端性能是否真正改善。
更多推荐




所有评论(0)