## 引言

在大模型训练、推理和推荐网络中,计算图里经常同时存在重复模块、独立分支,以及运行在不同硬件单元上的算子。当输入 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 实测选择端到端更优的方案。

判断多流优化是否有效,最终只需要回到三个问题:任务是否真正重叠,资源是否能够承载,以及端到端性能是否真正改善。

GE仓地址:https://gitcode.com/cann/ge

Logo

1331

更多推荐