first commit

This commit is contained in:
ylhan
2026-08-20 17:20:09 +08:00
commit 8049b6f58d
14 changed files with 1649 additions and 0 deletions
+92
View File
@@ -0,0 +1,92 @@
# 阶段 5:HAL(设备抽象)✅
> 2026-08-15。对应规划阶段 5。源码:`src/iree/compiler/src/iree/compiler/Dialect/HAL/`。
> HAL 既是「设备抽象层」,也是「codegen 的入口」(通过 TargetBackend)。
## 1. HAL 的职责
HAL(Hardware Abstraction Layer)把「设备」抽象成统一的概念,屏蔽 CPU/CUDA/Vulkan 等差异,
并把 Stream 层已经调度好的 `stream.cmd.*` 命令转成 `hal.*` 设备操作。
核心抽象有五个:**device、buffer/buffer_view、allocator、command_buffer、executable**(外加 channel 通信)。
## 2. 核心 op(`IR/HALOps.td`)
| 类别 | 关键 op | 作用 |
|---|---|---|
| **Device** | `hal.device.query`、`hal.device.allocator`、`hal.devices.get/count`、`hal.device.resolve` | 查询设备属性、获取设备 |
| **Buffer** | `hal.buffer.subspan/load/store/length`、`hal.buffer.assert` | 设备内存 buffer |
| **BufferView** | `hal.buffer_view.create`、`hal.buffer_view.buffer`、`hal.buffer_view.assert` | 带 shape/type 的 buffer 视图 |
| **Allocator** | `hal.allocator.allocate/import/select` | 内存分配 |
| **CommandBuffer** | `hal.command_buffer.create/dispatch/copy_buffer/fill_buffer/execution_barrier/finalize` | **记录命令**(核心) |
| **DeviceQueue** | `hal.device.queue.execute/execute.indirect/copy/fill/flush` | 提交命令队列 |
| **Executable** | `hal.executable`、`hal.executable.variant`、`hal.executable.export`、`hal.executable.binary` | 设备可执行代码 |
| **Channel** | `hal.channel.create/rank_and_count/split` | 多设备通信 |
## 3. Target Backend —— codegen 的入口(关键)
`HAL/Target/` 定义了 **TargetBackend** 抽象(`TargetBackend.cpp/h` + `TargetRegistry.cpp`):
- 每个后端(LLVM-CPU、LLVM-GPU/CUDA、SPIR-V/Vulkan 等)实现一个 TargetBackend
- 编译时按 `--iree-hal-target-backends=llvm-cpu` 选择后端
- **可执行体的 codegen 就发生在这里**:`ConfigureExecutables` → `TranslateExecutables`
会调用对应 TargetBackend,把 `flow.executable` 里的 linalg 编译成设备代码
> 这就是阶段 5(HAL)和阶段 6(codegen)的连接点:HAL 的 TargetBackend 是 codegen 的调度者。
## 4. 关键 pass(`Transforms/` + `Conversion/`)
| pass | 文件 | 作用 |
|---|---|---|
| `ConvertToHALPass` | ConvertToHAL.cpp | **Stream → HAL**(主入口) |
| `AssignTargetDevicesPass` / `MaterializeTargetDevicesPass` | 同名 | 目标设备分配 |
| `ResolveDevicePromisesPass` / `ResolveDeviceAliasesPass` | 同名 | 设备解析 |
| `ConfigureExecutablesPass` | ConfigureExecutables.cpp | 配置可执行体(选后端、变体) |
| `TranslateExecutablesPass` | TranslateExecutables.cpp | **调用后端做 codegen** |
| `LinkExecutablesPass` / `SerializeExecutablesPass` | 同名 | 链接 / 序列化可执行体 |
| `PruneExecutablesPass` / `HoistExecutableObjectsPass` | 同名 | 裁剪 / 提升可执行体对象 |
| `ElideRedundantCommandsPass` | ElideRedundantCommands.cpp | 消除冗余命令 |
**Conversion/**:
- `StreamToHAL/` —— Stream → HAL 转换
- `HALToVM/` —— HAL → VM 转换(阶段 7 的入口)
- `TypeConverter.cpp` —— 类型转换
## 5. IR 变换(阶段 2 已见,精简)
```mlir
// ConvertToHALPass 之后:stream.executable → hal.executable.variant
hal.executable private @matmul_dispatch_0 {
hal.executable.variant public @embedded_elf_x86_64 target(#executable_target_embedded_elf_x86_64) {
hal.executable.export public @matmul_dispatch_0_matmul_2x2x4_f32 ordinal(0) layout(#pipeline_layout)
attributes {workgroup_size = [1 : index, 1 : index, 1 : index]}
builtin.module { llvm.func @matmul_dispatch_0_matmul_2x2x4_f32(...) { ... } } // 已 codegen 成 LLVM
}
}
// #pipeline_layout 定义缓冲区绑定(2 ReadOnly + 1 输出 storage_buffer)
```
## 6. 与 TVM 0.6 对照
| HAL 概念 | TVM 0.6 | 说明 |
|---|---|---|
| hal.device / allocator | DeviceAPI(CPU/GPU) | 设备抽象 |
| hal.buffer / buffer_view | DLTensor / NDArray | 内存 + 元数据 |
| hal.command_buffer | 无显式对应(TVM 直接生成 kernel 调用) | IREE 显式建模命令录制 |
| hal.executable | 编译出的 kernel(.so / .ptx) | 设备代码 |
| TargetBackend | codegen 的 build_module 分派 | 后端注册 |
## 7. 源码阅读路径
```
src/iree/compiler/src/iree/compiler/Dialect/HAL/
├── IR/HALOps.td # op 定义(先读,认识五类抽象)
├── Target/TargetBackend.h # 后端抽象(codegen 入口)
├── Target/TargetRegistry.cpp # 后端注册表
├── Target/Devices/ # 具体设备
├── Transforms/ConvertToHAL.cpp # Stream → HAL
├── Transforms/TranslateExecutables.cpp # 调用后端 codegen
└── Conversion/StreamToHAL/ # 转换细节
```
> 学习建议:读 `TargetBackend.h` 理解「后端如何抽象」,这是 HAL 和 codegen 的接口。
> `hal.imports.mlir` 列出了 HAL 模块对外暴露的所有函数(就是 VM 层 import 的那些)。