Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
0ec49b0
fix(rocm): resolve the build architecture in one place, not three
demandal25 Aug 20, 2026
afc2ad1
Merge branch 'amd-integration' into fix-build-arch-resolver
demandal25 Aug 20, 2026
d44b1ee
Merge branch 'amd-integration' into fix-build-arch-resolver
demandal25 Aug 20, 2026
1937e0c
fix(rocm): canonicalize the resolved arch list, and make the agreemen…
demandal25 Aug 20, 2026
4d1335d
fix(rocm): validate the arch list before publishing it to the environ…
demandal25 Aug 20, 2026
6e8773c
fix(rocm): publish the arch list before validating, and restore it on…
demandal25 Aug 20, 2026
7bdc2c9
fix(rocm): publish the validated arch list, not the resolved superset
demandal25 Aug 20, 2026
b2f586d
perf(rocm): cache the rocminfo probe; sharpen the fallback warning an…
demandal25 Aug 20, 2026
b3fd023
fix(rocm): repair the comments the cache invalidated, and widen probe…
demandal25 Aug 20, 2026
1942578
fix(rocm): route explicit arch lists through the resolver too, and wa…
demandal25 Aug 20, 2026
4e50a4d
fix(rocm): make the GPU-less warning test order-independent; correct …
demandal25 Aug 20, 2026
4841493
fix(rocm): scope architecture detection to the process-visible GPUs
demandal25 Aug 20, 2026
c3c9fb1
fix(rocm): let the PyTorch check filter instead of failing the whole …
demandal25 Aug 20, 2026
fdb8f38
docs+test(rocm): match the resolver docstring to the code, cover the …
demandal25 Aug 20, 2026
e512b84
fix(rocm): narrow only the GPU-less fallback; handle ROCR and the -1 …
demandal25 Aug 20, 2026
a421230
fix(rocm): keep resolution provenance through the callers; fix visibi…
demandal25 Aug 20, 2026
5f35c76
fix(rocm): make visibility parsing total and check every composing layer
demandal25 Aug 20, 2026
14fb0e5
fix(rocm): leave ROCR scoping to rocminfo, which already applies it
demandal25 Aug 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions amd-flashinfer-jit-cache/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pip install amd-flashinfer amd-flashinfer-jit-cache

## Architecture Support

This package is built specifically for the **AMD MI300 series (gfx942)** architecture.
This package is built for whichever architectures the build host resolves to. `flashinfer.aot_hip` asks `hip_utils.resolve_target_archs()`, which takes `FLASHINFER_ROCM_ARCH_LIST` if set, else the supported GPUs actually present, else every supported architecture (gfx942 and gfx950) with a warning. Set the variable to pin a single target.

Check the package version and tags to ensure compatibility with your GPU architecture.

Expand All @@ -32,12 +32,12 @@ python -m build --wheel
The build process will:

1. Generate kernel specifications using `flashinfer.aot_hip`
2. Compile kernels for the gfx942 architecture
2. Compile kernels for the resolved architectures (see Architecture Support)
3. Package compiled `.so` files into the wheel

## Environment Variables

- `FLASHINFER_ROCM_ARCH_LIST`: Target architecture (default: "gfx942")
- `FLASHINFER_ROCM_ARCH_LIST`: Target architectures, comma- or semicolon-separated. Unset means detect, then fall back to all supported.
- `HIP_PATH`: Path to ROCm/HIP installation (auto-detected if not set)

## License
Expand Down
56 changes: 39 additions & 17 deletions flashinfer/aot_hip.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,25 +208,47 @@ def compile_and_package_modules(
final_config.update(config)
config = final_config

# ROCm Arch: Ensure env var is set or create/validate using CompilationContext
# ROCm arch: resolve once, then validate.
#
# Publishing the result back into the environment is deliberate, not
# incidental bookkeeping: the AITER shim resolves its own build architecture
# from FLASHINFER_ROCM_ARCH_LIST (jit/aiter_source.py), and an AOT build has
# no other channel to tell it what this build targets. Without this, a shim
# built during an AOT run on a mixed or GPU-less host can disagree with the
# kernels it is packaged alongside.
#
# It is a process-global side effect that outlives the call, which is worth
# replacing with an explicit parameter threaded through the AOT -> JIT
# boundary. That is a wider change than this one; leaving the lifetime
# unchanged here keeps this commit to the resolution bug it is fixing.
from .compilation_context_hip import CompilationContext

if "FLASHINFER_ROCM_ARCH_LIST" not in os.environ:
# Auto-detect or use default by creating a local context
compilation_context = CompilationContext()
detected_archs = ",".join(sorted(compilation_context.TARGET_ROCM_ARCHS))
os.environ["FLASHINFER_ROCM_ARCH_LIST"] = detected_archs
if verbose:
print(f"Auto-detected ROCm architectures: {detected_archs}")
else:
# Validate provided arch list by creating a local context
arch_list = os.environ["FLASHINFER_ROCM_ARCH_LIST"]
CompilationContext() # Validates arch_list set via env var
if verbose:
print(f"Using ROCm architectures: {arch_list}")

# Verify paths are correct
rocm_arch_list = os.environ["FLASHINFER_ROCM_ARCH_LIST"]
# Validate first, publish after. Publishing before would make
# CompilationContext resolve from the environment and classify the GPU-less
# fallback as an "env" request, which forfeits the fallback-only narrowing
# and fails an arch-specific wheel on the half it cannot build. Resolving
# twice is cheap now: rocminfo_gpu_agents is cached and the GPU-less warning
# is emitted once per message.
#
# Publishing only on success also means a failed build cannot leave
# FLASHINFER_ROCM_ARCH_LIST pointing somewhere for whatever runs next.
context = CompilationContext() # raises if nothing in the list is usable

# Publish what will *actually* be compiled. Validation drops architectures
# it cannot serve with a warning rather than raising, provided at least one
# survives, so the resolved list can be a strict superset of the built one.
# The AITER shim resolves its own target from this variable, so leaving the
# superset would have it build for an architecture the packaged kernels were
# not compiled for -- the exact failure this PR exists to remove.
#
# Taken from arch_flags rather than TARGET_ROCM_ARCHS because that is a set;
# order is meaningful, both on the hipcc command line and to AITER.
rocm_arch_list = ",".join(
flag.removeprefix("--offload-arch=") for flag in context.arch_flags
)
os.environ["FLASHINFER_ROCM_ARCH_LIST"] = rocm_arch_list
if verbose:
print(f"Target ROCm architectures: {rocm_arch_list}")

# Print summary
if verbose:
Expand Down
46 changes: 13 additions & 33 deletions flashinfer/compilation_context_hip.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,9 @@
"""

import logging
import os

import torch

from . import hip_utils
from .arch_caps import normalize_arch

logger = logging.getLogger(__name__)

Expand All @@ -50,40 +47,23 @@ def __init__(self):
"""
import torch.utils.cpp_extension as torch_cpp_ext

# Get architecture list from env or auto-detect
arch_list = os.environ.get("FLASHINFER_ROCM_ARCH_LIST")
if arch_list is None:
arch_list = self._auto_detect_archs()
if arch_list:
logger.info(f"Auto-detected ROCm architectures: {arch_list}")

# Comprehensive validation (all 3 checks)
# One resolver for every path that asks "what are we building for", so
# this cannot disagree with the validation in hip_utils -- it used to,
# returning gfx950 here while validation checked gfx942.
# Pass None rather than a pre-resolved string. Resolution carries
# provenance -- explicit / env / detected / fallback -- and handing back
# the resolved string would re-enter the resolver as "explicit",
# discarding it. Only the GPU-less "fallback" may be narrowed to what
# PyTorch actually ships, so losing the origin here turns a buildable
# half into a hard failure on an arch-specific wheel.
self.arch_flags, self.TARGET_ROCM_ARCHS = (
hip_utils.validate_flashinfer_rocm_arch(
arch_list=arch_list, torch_cpp_ext_module=torch_cpp_ext, verbose=False
arch_list=None, torch_cpp_ext_module=torch_cpp_ext, verbose=False
)
Comment thread
demandal25 marked this conversation as resolved.
)

def _auto_detect_archs(self) -> str:
"""Auto-detect ROCm architectures from supported system devices.

Only devices whose gcnArchName is in FLASHINFER_SUPPORTED_ROCM_ARCHS are
considered, so unsupported integrated GPUs are silently ignored here rather
than being passed on to validate_flashinfer_rocm_arch for filtering.
"""
try:
indices = hip_utils.get_supported_device_indices()
if indices:
archs = {
normalize_arch(torch.cuda.get_device_properties(i).gcnArchName)
for i in indices
}
return ",".join(sorted(archs))
logger.warning("No supported ROCm devices detected, defaulting to gfx942")
return "gfx942"
except Exception as e:
logger.warning(f"Failed to auto-detect ROCm device architectures: {e}")
return "gfx942"
logger.info(
"Target ROCm architectures: %s", ",".join(sorted(self.TARGET_ROCM_ARCHS))
)

def get_hipcc_flags_list(self) -> list[str]:
"""
Expand Down
Loading
Loading