blob: 7ef7cbb3429eca162b680ff9c7d7be8fc325d1d9 [file] [log] [blame] [view]
# HAL Driver Features
Heterogeneity is one of IREE's core design principles. IREE aims to support
various accelerators for compute, ranging from general purpose CPUs, GPUs, to
other special purpose accelerators. IREE provides a
[Hardware Abstraction Layer (HAL)][iree-hal] as a common interface to these
accelerators. IREE exposes it via an [C API][iree-hal-c-api] for programmers and
an MLIR [dialect][iree-hal-dialect] for compilers.
Heterogeneity inevitably means IREE needs to provide a solution for managing
different features on different accelerators and their availability. This doc
describes the designs and mechanisms.
## General HAL Driver Features
IREE uses compilers to generate native code for each accelerator, serialize the
native code, and embed the code in one flat byte code following FlatBuffer
encoding format. The native code embedded in the final FlatBuffer file will
indicate the target architecture and required feature sets. At runtime IREE
selects a HAL driver meeting all the requirements to dispatch the workload to.
[TODO: describe the HAL functionality, C API, and dialect abstraction]
## Vulkan HAL Driver Features
Vulkan has many mechanisms for supporting different hardware implementations:
versions, extensions, features, limits. Vulkan uses SPIR-V to express the GPU
program but Vulkan is just one client SPIR-V supports. So SPIR-V has its own
mechanisms for supporting different clients: versions, capabilities, extensions.
The mechanism in these two domains bear lots of similarity, but they are not
exactly the same. We need to bridge these two worlds inside IREE.
IREE has its own [Vulkan dialect][iree-vulkan-dialect], which defines the Vulkan
target environment, including [versions][iree-vulkan-base-td],
[extensions][iree-vulkan-base-td], [features][iree-vulkan-cap-td]. These
definitions leverage MLIR attribute for storage, parsing/printing, and
validation. For example, we can have the following Vulkan target environment:
```
target_env = #vk.target_env<
v1.1, r(120),
[VK_KHR_spirv_1_4, VK_KHR_storage_buffer_storage_class],
{
maxComputeSharedMemorySize = 16384 : i32,
maxComputeWorkGroupInvocations = 1024: i32,
maxComputeWorkGroupSize = dense<[128, 8, 4]>: vector<3xi32>,
subgroupFeatures = 7: i32,
subgroupSize = 64 : i32
}
>
```
The above describes a Vulkan implementation that supports specification version
1.1.120, supports `VK_KHR_spirv_1_4` and `VK_KHR_storage_buffer_storage_classs`
extensions, has a max compute workgroup invocation of 1024, and so on.
The above bears lots of similarity with the output of the
[`vulkaninfo`][vulkaninfo] utility. That's intended: `vulkaninfo` gives a
detailed dump of a Vulkan implementation by following the structures of all the
registered extensions to the specification. We pick relevant fields from it to
compose the list in the above to drive code generation. These are just different
formats for expressing the Vulkan implementation; one can image having a tool to
directly dump the MLIR attribute form used by IREE from the `vulkaninfo`'s JSON
dump.
When compiling ML models towards Vulkan, one specifies the target environment as
a `#vk.target_env` attribute assembly via the
[`iree-vulkan-target-env`][iree-vulkan-target-env] command-line option. At the
moment only one target environment is supported; in the future this is expected
to support multiple ones so that one can compile towards different Vulkan
implementations at once and embed all of them in the final FlatBuffer and select
at runtime. Another command-line option, `iree-vulkan-target-triple` is also
available to allow specifying common triples and avoiding the lengthy target
environment assembly string. `iree-vulkan-target-triple` will be overridden by
`iree-vulkan-target-env` if both are given.
Under the hood, this Vulkan target environment is then converted to the SPIR-V
target environment counterpart to drive code generation. The conversion happens
in one of Vulkan dialect's [utility function][iree-vulkan-target-conv]. The
converted SPIR-V target environment is [attached][iree-spirv-target-attach] to
the dispatch region's module for SPIR-V passes to use.
SPIR-V's target environment is very similar to the Vulkan target environment in
the above; it lives in upstream MLIR repo and is documented
[here][mlir-spirv-target] and implemented in SPIR-V dialect's
[`SPIRVAttribues.h`][mlir-spirv-attr] and
[`TargetAndABI.td`][mlir-spirv-target-td].
[PR #3469][pr-3469], along with patch [D89364][d89364], shows an example of the
changes needed to add support for the
[VK_NV_cooperative_matrix][vk-coop-mat-ext] extension for Vulkan/SPIR-V. The
overall steps are as follows:
1. Add the enum corresponding to the extension to `VK_ExtensionAttr` in
[VulkanBase.td][iree-vulkan-base-td].
1. Add necessary capability bits to [`VK_CapabilitiesAttr`][iree-vulkan-cap-td].
1. Add a corresponding attribute to the `SPV_ResourceLimitsAttr` in
[TargetAndABI.td][mlir-spirv-target-td]. (Note: The corresponding SPIR-V
extension is likely already defined in
[`SPV_ExtensionAttr`][mlir-spirv-extensions-attr])
1. Convert the capability bits specified in the attribute added to
`VK_CapabilitiesAttr` to the attribute added to `SPV_ResourceLimitsAttr`.
[d89364]: https://reviews.llvm.org/D89364
[iree-hal]: https://github.com/google/iree/tree/main/iree/hal
[iree-hal-c-api]: https://github.com/google/iree/blob/main/iree/hal/api.h
[iree-hal-dialect]: https://github.com/google/iree/tree/main/iree/compiler/Dialect/HAL
[iree-vulkan-dialect]: https://github.com/google/iree/tree/main/iree/compiler/Dialect/Vulkan
[iree-vulkan-base-td]: https://github.com/google/iree/blob/main/iree/compiler/Dialect/Vulkan/IR/VulkanBase.td
[iree-vulkan-cap-td]: https://github.com/google/iree/blob/main/iree/compiler/Dialect/Vulkan/IR/VulkanAttributes.td
[iree-vulkan-target-env]: https://github.com/google/iree/blob/b4739d704de15029cd671e53e7d7e743f4ca2e35/iree/compiler/Dialect/HAL/Target/VulkanSPIRV/VulkanSPIRVTarget.cpp#L66-L70
[iree-vulkan-target-triple]: https://github.com/google/iree/blob/main/iree/compiler/Dialect/Vulkan/Utils/TargetEnvUtils.cpp
[iree-vulkan-target-conv]: https://github.com/google/iree/blob/b4739d704de15029cd671e53e7d7e743f4ca2e35/iree/compiler/Dialect/Vulkan/Utils/TargetEnvUtils.h#L29-L42
[iree-spirv-target-attach]: https://github.com/google/iree/blob/b4739d704de15029cd671e53e7d7e743f4ca2e35/iree/compiler/Dialect/HAL/Target/VulkanSPIRV/VulkanSPIRVTarget.cpp#L228-L240
[mlir-spirv-extensions-attr]: https://github.com/llvm/llvm-project/blob/076305568cd6c7c02ceb9cfc35e1543153406d19/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td#L314
[mlir-spirv-target]: https://mlir.llvm.org/docs/Dialects/SPIR-V/#target-environment
[mlir-spirv-attr]: https://github.com/llvm/llvm-project/blob/076305568cd6c7c02ceb9cfc35e1543153406d19/mlir/include/mlir/Dialect/SPIRV/SPIRVAttributes.h
[mlir-spirv-target-td]: https://github.com/llvm/llvm-project/blob/076305568cd6c7c02ceb9cfc35e1543153406d19/mlir/include/mlir/Dialect/SPIRV/TargetAndABI.td
[pr-3469]: https://github.com/google/iree/pull/3469
[vk-coop-mat-ext]: khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_NV_cooperative_matrix.html
[vulkaninfo]: https://vulkan.lunarg.com/doc/view/latest/linux/vulkaninfo.html