# 阶段 4b:Stream(异步调度)✅ > 2026-08-15。对应规划阶段 4 后半。源码:`src/iree/compiler/src/iree/compiler/Dialect/Stream/`。 > **这是 IREE 最有特色、也是 TVM 没有对应物的一层,值得重点理解。** ## 1. Stream 的职责:把同步图变成异步执行模型 Flow 层产出的还是「同步的图」(每个 op 依赖前一个的 result)。Stream 层把它变成**异步执行模型**: - 每个计算(dispatch)变成可异步提交的工作 - 用 **timepoint**(类似 future/fence)显式表达「某批异步工作何时完成」 - 用 **resource** 管理内存的生命周期(分配/持有/释放) - 用 **affinity** 标注每个 op 在哪个设备上执行 这一层是 IREE 支持多设备异步调度的核心。 ## 2. 核心概念 ### (1) timepoint —— 异步同步原语(灵魂) `!stream.timepoint` = 一个「未来某个时刻会完成」的句柄,用来表达数据依赖和同步: ```mlir // stream.async.execute 提交一批异步工作,返回 (results, timepoint) %results, %result_timepoint = stream.async.execute ... { %4 = stream.async.dispatch @matmul_dispatch_0::@...(%arg2[...], %arg3[...]) : ... stream.yield %4 : !stream.resource<...> } => !stream.timepoint // stream.timepoint.await 等待 timepoint 完成,取出结果 %2 = stream.timepoint.await %result_timepoint => %results : !stream.resource<...> ``` ### (2) resource —— 内存资源(带显式生命周期) tensor(值语义)在 Stream 层变成 `!stream.resource<...>`(带大小),生命周期显式管理: ```mlir %1 = stream.tensor.import on(#hal.device.affinity<@__device_0>) %arg0 : !hal.buffer_view -> tensor<2x4xf32> in !stream.resource{%0} ``` resource 有:分配(alloc)、持有(retain)、释放(release)、子视图(subview)、 瞬态(transient)。生命周期由 **ARC(Automatic Reference Counting)** pass 自动管理。 ### (3) affinity —— 设备亲和性 每个 op 标注 `on(#hal.device.affinity<@__device_0>)`,表示在哪个设备上执行。 跨设备的 op 需要 `stream.async.transfer` 来传输数据。 ## 3. 四个抽象层次(关键!) Stream dialect 内部有从高到低的层次,编译时逐步下降: | 层次 | op 前缀 | 何时产生 | 说明 | |---|---|---|---| | tensor | `stream.tensor.*` | ConvertToStreamPass | 值语义张量(最接近 Flow) | | async | `stream.async.*` + `stream.timepoint.*` | ScheduleExecutionPass | 异步执行 + timepoint 同步 | | cmd | `stream.cmd.*` | 接近 HAL | 命令缓冲(dispatch/copy/fill/flush) | | resource | `stream.resource.*` | 全流程 | 内存资源生命周期 | ## 4. 核心 op(`IR/StreamOps.td`) - **tensor 层**:`stream.tensor.import/export`、`stream.tensor.dispatch`、`stream.tensor.sizeof` - **async 层**:`stream.async.execute`、`stream.async.dispatch`、`stream.async.transfer`、 `stream.async.copy/fill/load/store`、`stream.async.barrier` - **timepoint**:`stream.timepoint.await/barrier/join/import/export/immediate` - **cmd 层**:`stream.cmd.dispatch/execute/copy/fill/flush/invalidate/serial/concurrent` - **resource**:`stream.resource.alloc/dealloca/size/retain/release/subview/transients` - **executable**:`stream.executable`、`stream.binding.subspan` ## 5. 关键 pass(`Transforms/` + `Analysis/`) | pass | 文件 | 作用 | |---|---|---| | `ConvertToStreamPass` | ConvertToStream.cpp | Flow → Stream(核心入口) | | `ScheduleExecutionPass` | ScheduleExecution.cpp | **调度**:图 → async.execute + timepoint | | `ScheduleConcurrencyPass` | ScheduleConcurrency.cpp | 并发调度(并行 workgroup 重叠) | | `PropagateTimepointsPass` | PropagateTimepoints.cpp | timepoint 传播(优化同步点) | | `ScheduleAllocationPass` | ScheduleAllocation.cpp | 资源分配调度 | | `AutomaticReferenceCountingPass` | AutomaticReferenceCounting.cpp | **ARC**:自动引用计数管理资源生命周期 | | `ElideTimepointsPass` / `ElideAsyncCopiesPass` | 同名 | 消除冗余 timepoint / async copy | | `ReuseAllocationsPass` / `RefineUsagePass` | 同名 | 内存复用 / 使用细化 | **Analysis/**(调度前的分析): - `Affinity.cpp` —— 设备亲和性分析 - `Partitioning.cpp` —— 分区分析 - `ResourceHazards.cpp` / `ResourceUsage.cpp` —— 资源冲突 / 使用分析 ## 6. IR 变换(阶段 2 已见,精简回顾) ```mlir // ConvertToStreamPass:Flow → Stream,tensor 变 stream.resource,标上 affinity %7 = stream.tensor.dispatch on(#hal.device.affinity<@__device_0>) @matmul_dispatch_0::@...(%2, %5) : ... // ScheduleExecutionPass:包进 async.execute,产生 timepoint %results, %result_timepoint = stream.async.execute ... { ... } => !stream.timepoint %2 = stream.timepoint.await %result_timepoint => %results : !stream.resource<...> ``` ## 7. 与 TVM 0.6 对照 | Stream 概念 | TVM 0.6 | 说明 | |---|---|---| | timepoint / async.execute | **无直接对应** | TVM 的异步主要在 runtime(线程池/stream),不在编译期 IR 里显式建模 | | resource 生命周期 | **无**(TVM 的 buffer 生命周期由 runtime 管) | IREE 在编译期显式建模并 ARC | | affinity | device 注解 | 类似但 IREE 更显式 | | scheduling | 无(TVM 是同步图 + runtime 调度) | IREE 把调度变成 IR 变换 | **核心差异**:TVM 把「图是同步的、异步是 runtime 的事」;IREE 把「异步调度」提升为**编译期的显式 IR 层**, 可以针对多设备做静态调度优化。这就是为什么 IREE 在多设备/异构场景更强。 ## 8. 源码阅读路径 ``` src/iree/compiler/src/iree/compiler/Dialect/Stream/ ├── IR/StreamOps.td # op 定义(先读,认识 tensor/async/cmd/resource 四层) ├── Analysis/ # Affinity / Partitioning / ResourceHazards / ResourceUsage ├── Transforms/ConvertToStream.cpp # Flow → Stream ├── Transforms/ScheduleExecution.cpp # 异步调度(核心) ├── Transforms/PropagateTimepoints.cpp # timepoint 优化 └── Transforms/AutomaticReferenceCounting.cpp # 资源生命周期 ARC ``` > 学习建议:先读 `ScheduleExecution.cpp` 理解「怎么从同步图变异步」, > 再读 `PropagateTimepoints.cpp` 理解「timepoint 怎么优化」, > 最后读 `AutomaticReferenceCounting.cpp` 理解「资源生命周期怎么管」。