Files
TheRock/rocm-libraries/projects/hipblaslt/docs/conceptual/pci-chip-id-predicates-walkthrough.rst
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

175 lines
8.0 KiB
ReStructuredText

.. meta::
:description: Predicate selection walkthrough for the hipBLASLt library
:keywords: hipBLASLt, ROCm, library, runtime, predicate, selection
.. _predicate-selection-walkthrough:
*********************************************
PCI chip ID predicates walkthrough
*********************************************
Predicates are one of the essential integration points between the TensileLite build system and the hipBLASLt library runtime.
Predicates are built into the master solution libraries. They are files that contain information about which kernels are available
and their location. These files are loaded at runtime and used in the kernel selection process.
.. note::
This guide covers advanced technical concepts and is intended for highly experienced users and developers only.
Chip ID registry
-----------------------
The chip ID registry is a namespace in
`Tensile/AMDGPUPredicates.hpp <https://github.com/ROCm/rocm-libraries/blob/develop/projects/hipblaslt/tensilelite/include/Tensile/AMDGPUPredicates.hpp>`_ that
contains the official mapping of supported PCI chip IDs and their fallback relationships.
.. code-block:: yaml
- {PCIChipId: 0x75a3, DeviceName: AMD Instinct MI355X}
- {PCIChipId: 0x75a2, DeviceName: AMD Instinct MI355X}
Hardware predicates
-----------------------
Hardware predicates are the most coarse-grained predicates. They are used to qualify, or reject, a kernel based on
attributes that can be determined at runtime through system inspection. These include the processor type (for example, gfx1201),
the compute-unit counter (for example, 128), and, as of ROCm 7.13, the PCI chip ID (for example, 0x7890).
Building hardware predicates
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The source of truth for hardware predicates is in the hipBLASLt library logic (LL) files (``find . -name Logic``). In particular, as of
`TensileLite version 5.0.0 <https://github.com/ROCm/rocm-libraries/blob/273fcdc27e2f37d81420929d2105649494c9bb9d/projects/hipblaslt/tensilelite/Tensile/__init__.py>`_,
the standard four-statement metadata at the top of each LL is authoritative (some LLs could have fields omitted for backwards compatibility):
.. code-block:: yaml
- {MinimumRequiredVersion: 5.0.0}
- gfx950
- {Architecture: gfx950, CUCount: 64}
- [Device 75a3, Device 75a2]
In the TensileLite build system, the PCI chip ID is added as an ``Or``-style predicate, to support multiple device IDs
for the same device.
At build time, when the predicates are written to the master solution libraries, chip ID predicates are added as ``Or``-style conditions
to the top-level lazy lookup (``TensileLibrary_lazy_....dat/yaml``). For example, a snippet from ``TensileLibrary_lazy_gfx1201.yaml``
could appear as:
.. code-block:: yaml
predicate:
type: AMDGPU # <-- AMDGPU hardware predicate
value:
type: And
value:
- {type: Processor, value: gfx1201}
- {type: CUCount, value: 64}
# if only one chip ID is specified
- {type: PciChipId, value: 30032} # <-- placed directly alongside Process
# if multiple chip IDs are specified
- type: Or # <-- expanded into an `Or` conditioned list
value:
- {type: PciChipId, value: 30032}
- {type: PciChipId, value: 30583}
That is, groups of solutions are co-resident in a LL file and marked by a set of ``Device xxxx`` strings. This allows solution filtering
(predicate matching) to be performed at the lazy library level. Consequently, any candidate libraries that don't at least match the
processor and the current PCI chip ID (plus optional CU counts) will be skipped before the runtime code tries to load the library.
Using hardware predicates
^^^^^^^^^^^^^^^^^^^^^^^^^
How does this play out during runtime? When the lazy solution library is loaded, it is deserialized and the predicates are matched
against the known program constraints to determine which **loadable** libraries are relevant (match), and which are not (don't match).
Set ``TENSILE_DB`` to see how the chip IDs are matched at runtime. For example, take the output from a test library logic
that has the gfx1201 chip ID (7550) and another, random one:
.. code-block:: text
--------------------------------------------------------------------------------
PREDICATE: ExactLogic: Hardware
--------------------------------------------------------------------------------
[!!] And (3 predicates)
[OK] Processor gpu=gfx950:sramecc+:xnack- == sol=gfx950
[!!] CUCount gpu=256 == sol=64
[OK] Or (2 predicates)
[OK] PciChipId [AMD Instinct MI355X] gpu=0x75a3 == sol=0x75a3
[!!] PciChipId [AMD Instinct MI355X] gpu=0x75a3 == sol=0x75a2
--------------------------------------------------------------------------------
Result: NO MATCH
--------------------------------------------------------------------------------
Here you can see how different chip IDs are being selected against the known device properties.
Build-time row ordering (fallback-aware)
----------------------------------------
When a logic file declares multiple device IDs, ``tensilelite`` treats them as a **set**
for ordering purposes (not "first ID wins"). This matters because runtime selection is
``first-match-wins``, and ``PciChipId`` supports one-way fallback.
Fallback graph (example for ``gfx950`` variants):
.. code-block:: text
75a3 ---> 75a0
75a2 ---> 75a0
Interpretation:
- Arrow direction means "may fallback to".
- Source-like IDs (left) are more specific than fallback targets (right).
- Rows must be ordered so source-like exact rows are considered first.
The build-time comparator for hardware rows applies chip-ID precedence as follows:
#. **Chip-set present vs absent**: rows with chip IDs sort before rows without chip IDs.
#. **Exactness first**: smaller chip-ID sets sort first (for example,
``{75a3}`` before ``{75a3,75a0}``).
#. **Fallback-aware rank**: for equal-size sets, compare IDs by fallback-topology rank
(farther from fallback roots first), then by chip ID value for deterministic tie-breaks.
#. **The CU count**: if chip precedence does not decide the order, the higher ``CUCount`` sorts first.
Here is a minimal ordering example (for the same processor):
.. code-block:: text
1) {75a3}, CU=256
2) {75a3}, CU=64
3) {75a0}, CU=256
4) {75a0}, CU=64
5) {75a3,75a0}, CU=*
6) {no chip id}, CU=*
Why this matters:
- Device ``75a3`` can still use ``75a0`` fallback kernels at runtime.
- However, exact ``75a3`` rows are evaluated first, preventing broad/mixed rows from
accidentally shadowing more specific rows.
Runtime selection
-----------------
``ExactLogicLibrary::findBestSolution`` iterates hardware predicate rows in priority order.
For each row that matches the GPU, it calls ``HardwarePredicate::isFallbackMatch(hardware)``
to classify the match:
- Exact match (``isFallbackMatch`` returns false): The row's ``PciChipIdEqual`` target
matches the GPU's chip ID exactly (for example, an Instinct™ MI350 GPU matches a ``PciChipIdEqual(0x75a0)`` row),
or the row has no chip ID predicate at all. The solution is returned immediately.
- Fallback match (``isFallbackMatch`` returns true): The GPU matched via chip ID fallback
(for example, an Instinct MI355 GPU ``0x75a3`` matches an Instinct MI350 GPU ``0x75a0`` row through ``ChipIdRegistry``). The solution is
saved but the loop continues to search for an exact match.
After all rows are checked, if no exact match was found, the saved fallback solution is returned.
This ensures that device-specific solutions (Instinct MI355-targeted kernels) are always preferred over
fallback solutions (Instinct MI350 kernels running on an Instinct MI355 GPU), regardless of row ordering.
An exact match anywhere in the list beats a fallback match that appeared earlier.
.. important::
This means that the first fallback match is the one that is returned, and all subsequent ones are ignored.