Files
2026-08-20 17:20:09 +08:00

92 lines
4.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 阶段 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),读的时候注意版本。