# 阶段 4a:Flow(图级优化 + dispatch 划分)✅ > 2026-08-15。对应规划阶段 4 前半。源码:`src/iree/compiler/src/iree/compiler/Dialect/Flow/`。 > IR 变换示例见 [02-architecture.md](02-architecture.md) 边界 2。 ## 1. Flow 的职责 Flow 是 IREE 的**图级 IR**,在输入方言(linalg)和 Stream(异步)之间。两大职责: 1. **图级优化**:算子融合(fusion)、reshape 折叠、类型推导、量化转换、全局常量处理等 2. **dispatch 划分**:把图切成一个个 **dispatch region**,再 outline 成独立的 `flow.executable` —— 每个 dispatch = 一个可独立编译执行的 kernel(对应 TVM 里划分出的一个 kernel) ## 2. 核心 op(定义在 `IR/FlowOps.td`) | op | 作用 | |---|---| | `flow.tensor.empty/load/store/slice/reshape/update` | Flow 层的张量操作(值语义) | | `flow.tensor.barrier` | 张量屏障,标记 dispatch 边界(前身是 `iree_tensor_ext.compute_barrier`) | | `flow.tensor.transfer` | 跨设备张量传输 | | `flow.dispatch.region` | **dispatch region**:一个可执行单元(核心) | | `flow.dispatch` / `flow.dispatch.workgroups` | 调用 dispatch(启动一个 kernel) | | `flow.executable` / `flow.executable.export` | 可执行体 + 导出点 | | `flow.dispatch.workgroup_count/id/size` | workgroup 相关内建 | | `flow.channel.*` + `flow.collective.*` | 多设备通信(AllGather/AllReduce/AllToAll/SendRecv) | | `flow.parameter.load/write` | 参数(权重)处理 | ## 3. 关键 pass(`Transforms/` 目录) | pass | 文件 | 作用 | |---|---|---| | `ConvertToFlowPass` | ConvertToFlow.cpp | 输入方言 → Flow | | `FusionPreprocessingPass` / `ElementwiseOpFusionPass` / `FuseMultiUseElementwiseProducerPass` | (dispatch creation) | **算子融合**(elementwise 融合进 reduce/matmul) | | `FormDispatchRegionsPass` | FormDispatchRegions.cpp | **形成 dispatch region**(核心) | | `CloneProducersIntoDispatchRegionsPass` | (dispatch creation) | 把 producer 克隆进 dispatch region | | `ConvertDispatchRegionsToWorkgroupsPass` | ConvertRegionToWorkgroups.cpp | dispatch region → workgroup 语义 | | `OutlineDispatchRegionsPass` | OutlineDispatchRegions.cpp | **outline 成 flow.executable** | | `DeduplicateExecutablesPass` | DeduplicateExecutables.cpp | 去重相同 executable | | `CleanupTensorShapesPass` / `CaptureDynamicDimsPass` | 同名 .cpp | 形状清理 / 动态维度捕获 | ## 4. dispatch region 形成(核心概念) **dispatch region = 一个要交给 codegen 独立编译的计算单元**(对应一个 kernel 启动)。 形成逻辑(`FormDispatchRegionsPass`): 1. 以「root op」(如 `linalg.matmul`、reduction)为锚点 2. 把可融合的 elementwise producer 克隆进同一个 region(fusion) 3. 用 `flow.tensor.barrier` 标记 region 的输入/输出边界 4. 后续 outline 成 `flow.executable` IR 变化(阶段 2 已见,精简): ```mlir // FormDispatchRegionsPass 之后:matmul + fill 被包进 dispatch.region %6 = flow.dispatch.region -> (tensor<2x2xf32>) { %8 = linalg.fill ins(%cst : f32) outs(%7 : tensor<2x2xf32>) -> tensor<2x2xf32> %9 = linalg.matmul ins(%1, %3 : ...) outs(%8 : ...) -> tensor<2x2xf32> flow.return %9 : tensor<2x2xf32> } // OutlineDispatchRegionsPass 之后:outline 成 executable,主函数只剩 flow.dispatch 调用 flow.executable private @matmul_dispatch_0 { ... } // 独立的可执行体 %2 = flow.dispatch @matmul_dispatch_0::@matmul_dispatch_0_matmul_2x2x4_f32(%0, %1) : ... ``` ## 5. 与 TVM 0.6 对照 | IREE Flow | TVM 0.6 Relay | |---|---| | 图级优化(fusion/reshape/type propagation) | Relay 的 fusion / 图优化 pass | | dispatch region 形成 | 确定哪些算子合成一个 kernel(relay fusion 后的分组) | | flow.executable | 一个编译好的 kernel | | flow.tensor.*(值语义张量) | Relay 的 TensorType 表达式 | | flow.collective.* | Relay 里的通信算子(较晚版本才有) | ## 6. 源码阅读路径 ``` src/iree/compiler/src/iree/compiler/Dialect/Flow/ ├── IR/FlowOps.td # op 定义(TableGen)—— 先读这个,认识所有 op ├── IR/FlowOps.cpp # op 实现(verifier、folder、builder) ├── IR/FlowInterfaces.td # 接口定义(如 Dispatchable/Partitionable) ├── Transforms/FormDispatchRegions.cpp # dispatch 划分核心算法 ├── Transforms/OutlineDispatchRegions.cpp ├── Transforms/ConvertRegionToWorkgroups.cpp └── Conversion/TensorToFlow/ # tensor → flow 转换 ``` > 学习建议:先读 `FlowOps.td` 认 op,再看 `FormDispatchRegions.cpp` 理解划分算法。 > 划分算法在 IREE 3.x 已重构为基于「partitionable interface + workload」的方式 > (不是老的 DispatchableOpInterface),读的时候注意版本。