vllm_gaudi.patches
¶
Runtime monkey-patches applied when the HPU plugin is loaded.
Currently:
-
torch.accelerator.empty_cache— HPU's allocator does not implement thec10::DeviceAllocatorinterface, so the upstream helper raisesRuntimeError: Allocator for hpu is not a DeviceAllocator. We replace it with an HPU-safe variant that routes throughcurrent_platform.empty_cache()(a no-op on HPU). This also makes thecleanup_dist_env_and_memorypatch resilient to import-order issues. -
torch._C._host_emptyCache— does not exist on HPU; we install a no-op stub to preventAttributeErrorincleanup_dist_env_and_memory. -
vllm.distributed.parallel_state.cleanup_dist_env_and_memory— upstream (since vllm PR #34328) callstorch.accelerator.empty_cache(), which requires the device's allocator to be ac10::DeviceAllocator. We replace it with an HPU-safe variant that usescurrent_platform.empty_cache()instead (see GAUDISW-247825). -
vllm.v1.sample.ops.logprobs.batched_count_greater_than— upstream decorates this function with@torch.compile(dynamic=True, ...). Habana'srecipe_compilerbackend cannot handle the symbolic shapes produced bydynamic=True(and bymark_unbackedin the caller), raisingTypeError: Cannot convert symbols to int. We replace it with a plain (uncompiled) version of the same function. The replacement is deferred toload_general_pluginstime to avoid importingvllm.v1.sample.samplerduring early plugin registration, which would trigger a heavy import chain that interferes with platform initialisation. -
vllm.v1.sample.sampler.Sampler.gather_logprobs— upstream PR #38933 added twomark_unbacked()calls insidegather_logprobsto prevent 0->1 batch-size specialization recompiles forbatched_count_greater_thanon CUDA. On HPU,torch._dynamomarksmark_unbackedas a forbidden callable (is_forbidden=True), so tracing a compiledSamplerraisesAssertionError: Attempt to trace forbidden callable mark_unbackedfor any request withlogprobs=true. We replacegather_logprobswith an identical implementation that omits the twomark_unbackedcalls. HPU handles dynamic batch shapes without this hint. -
vllm.v1.core.block_pool.BlockPool.free_blocks— upstream PR #42656 ("Apply LRU policy only to proper cache entries") madefree_blockspartition freed blocks into with-hash / without-hash lists and issue two queue ops (prepend_n+append_n) on every engine step. When prefix caching is disabled every block's hash isNone, so the split is a no-op that only adds per-step CPU overhead — a measurable decode-throughput loss on small/low-batch models. We restore a single-pass free for theenable_caching=Falsecase and delegate to the original implementation when prefix caching is on. Remove once fixed upstream.
_hpu_accelerator_empty_cache
¶
HPU-safe replacement for torch.accelerator.empty_cache().
HPU's allocator does not implement the c10::DeviceAllocator
interface, so the upstream torch.accelerator.empty_cache() raises
RuntimeError. Route through current_platform.empty_cache
instead (which is None on HPU, making this a no-op).
Source code in vllm_gaudi/patches.py
_hpu_batched_count_greater_than
¶
HPU-safe replacement for batched_count_greater_than.
Identical logic to the upstream implementation but not wrapped in
torch.compile. The upstream decorator uses dynamic=True whose
symbolic shapes are incompatible with Habana's recipe_compiler
backend, and mark_unbacked in the caller prevents dynamic=False
from helping.
Source code in vllm_gaudi/patches.py
_hpu_cleanup_dist_env_and_memory
¶
_hpu_cleanup_dist_env_and_memory(
shutdown_ray: bool = False,
) -> None
HPU-safe replacement for cleanup_dist_env_and_memory.
Mirrors the upstream implementation but routes the device-side cache
release through current_platform.empty_cache() instead of
torch.accelerator.empty_cache() (which is incompatible with the
HPU allocator).
Source code in vllm_gaudi/patches.py
_hpu_free_blocks
¶
Single-pass BlockPool.free_blocks for enable_caching=False.
Upstream vLLM PR #42656 rewrote free_blocks to partition freed blocks
into with-hash / without-hash lists and issue two queue ops
(prepend_n + append_n) on every engine step. When prefix caching
is disabled, every block's hash is None, so that split is a no-op that
only adds per-step CPU work; on short decode steps (small model / low
batch) it is a measurable fixed overhead (~3.5% output-token throughput on
llama-3.1-8B FP8, 1 card, 4096/1024, mc=8 — see GAUDISW-250180). Free in
a single pass in that case; delegate to the original (upstream)
implementation when prefix caching is enabled so #42656's LRU ordering is
preserved. Remove this patch once the fix lands upstream.
Source code in vllm_gaudi/patches.py
_hpu_gather_logprobs
¶
HPU-safe replacement for Sampler.gather_logprobs.
Identical logic to the upstream implementation (vllm PR #38933) but with
the two mark_unbacked() calls removed. On HPU, mark_unbacked is a
forbidden callable in torch._dynamo (is_forbidden=True). When the
compiled Sampler traces gather_logprobs, hitting mark_unbacked
raises AssertionError: Attempt to trace forbidden callable. HPU does
not need this CUDA-specific recompile hint.
Upstream ref: https://github.com/vllm-project/vllm/pull/38933
Source code in vllm_gaudi/patches.py
_patch_batched_count_greater_than
¶
Replace batched_count_greater_than in the sampler & logprobs modules.
Called from the load_general_plugins hook so that the heavy
vllm.v1.sample.* import chain runs after platform initialisation.
Source code in vllm_gaudi/patches.py
_patch_cleanup_dist_env_and_memory
¶
Install the HPU-safe cleanup_dist_env_and_memory replacement.
Deferred to load_general_plugins time (rather than apply() at
platform-registration time) so the vllm.distributed.parallel_state
import chain runs after the platform is initialised and after
vllm.utils.torch_utils has finished importing (see apply() and
the module-level NOTE — GAUDISW-249622).
Source code in vllm_gaudi/patches.py
_patch_free_blocks
¶
Install the single-pass free_blocks fast path for APC-disabled runs.
Deferred to load_general_plugins time (same as the other patches) so
the vllm.v1.core import runs after platform initialisation.
Idempotent: only wraps the original free_blocks once.
Source code in vllm_gaudi/patches.py
_patch_gather_logprobs
¶
Replace Sampler.gather_logprobs with the HPU-safe variant.
Called from the load_general_plugins hook (same as
_patch_batched_count_greater_than) so that vllm.v1.sample.*
imports run after platform initialisation.
Guarded by inspect.getsource so this is a no-op on vLLM versions
that predate PR #38933 (i.e. where gather_logprobs does not call
mark_unbacked).
Source code in vllm_gaudi/patches.py
_patch_hf3fs_mock_client_for_cpu_only
¶
Patch HF3FS mock client to avoid CUDA stream waits on CPU-only builds.
Upstream mock client unconditionally calls
torch.cuda.current_stream().wait_event(event) in batch_write.
In environments where PyTorch is not compiled with CUDA, that path throws
and the method returns -1 for writes, causing connector unit tests to
fail. This patch keeps the same behavior but skips CUDA synchronization when
CUDA is unavailable.
Source code in vllm_gaudi/patches.py
apply
¶
Install all HPU runtime monkey-patches.
Source code in vllm_gaudi/patches.py
patch_hf3fs_mock_client
¶
Guard CUDA sync in the HF3FS mock client on non-CUDA platforms.
The upstream mock client's batch_write unconditionally calls
torch.cuda.current_stream().wait_event(event), which raises
RuntimeError on platforms without CUDA (e.g. HPU). This helper
installs the CPU-safe replacement for batch_write.
Called from register_utils() (general plugin) rather than
apply() (platform plugin) to avoid circular imports — the mock
client transitively imports vllm.config which is not yet fully
initialized during platform registration.