Files
note_AI_compiler/iree/07-hal.md
T
2026-08-20 17:20:09 +08:00

5.0 KiB
Raw Blame History

阶段 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 已见,精简)

// 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 的那些)。