feat(vllm): Tackle out of memory errors (EAI-8058) - #251
Conversation
6190726 to
ee202f0
Compare
|
A few observations from a read of this change:
On the stack: #284's diff against this branch removes the sysfs fallback, its tests and the docs bullet — looks unintended. |
…e documentation Signed-off-by: Roman Sirokov <roman.sirokov@amd.com>
…back Address review feedback on PR #251: - resolve_gpu_indices now validates an explicit --gpu <index> against the DRM sysfs fallback's device count when amd-smi is unavailable, instead of only the amd-smi count. Previously an out-of-range index was silently accepted on a host with no amd-smi (sysfs works) and only failed later inside the engine. - read_drm_vram_usage no longer treats an unreadable mem_info_vram_used counter as 0 bytes used (which made the card look 100% free -- exactly what --gpu auto prefers first); it now skips that card instead. - read_drm_vram_usage withholds telemetry entirely when more than one AMD DRM card is present, since ascending card<N> order is only guaranteed to match HIP's compute-topology ordinal on a single-GPU host (an APU passes the same vendor + mem_info_vram_total filter as a discrete GPU, so an APU+dGPU host could previously feed a diverged ordinal into HIP_VISIBLE_DEVICES). - docs/vllm.md: corrected the fallback description, which only ever probes amd-smi (never rocm-smi) before falling back to DRM sysfs. Extracted the count-fallback logic into a new effective_gpu_count helper shared by --gpu auto ranking and --gpu <index> validation, and added unit tests for all of the above. Signed-off-by: Roman Sirokov <roman.sirokov@amd.com>
ee202f0 to
a97a39f
Compare
|
Thanks for the detailed review — pushed a fix commit (a97a39f) addressing the concrete bugs:
Added unit tests for all four ( On the Gherkin scenario: I didn't add one for the "no On #284: worth double-checking before merging that stack — its diff against this branch appears to drop the sysfs fallback, its tests, and the docs bullet, which does look unintended given this PR is what introduces them. |
…back Address review feedback on PR #251: - resolve_gpu_indices now validates an explicit --gpu <index> against the DRM sysfs fallback's device count when amd-smi is unavailable, instead of only the amd-smi count. Previously an out-of-range index was silently accepted on a host with no amd-smi (sysfs works) and only failed later inside the engine. - read_drm_vram_usage no longer treats an unreadable mem_info_vram_used counter as 0 bytes used (which made the card look 100% free -- exactly what --gpu auto prefers first); it now skips that card instead. - read_drm_vram_usage withholds telemetry entirely when more than one AMD DRM card is present, since ascending card<N> order is only guaranteed to match HIP's compute-topology ordinal on a single-GPU host (an APU passes the same vendor + mem_info_vram_total filter as a discrete GPU, so an APU+dGPU host could previously feed a diverged ordinal into HIP_VISIBLE_DEVICES). - docs/vllm.md: corrected the fallback description, which only ever probes amd-smi (never rocm-smi) before falling back to DRM sysfs. Extracted the count-fallback logic into a new effective_gpu_count helper shared by --gpu auto ranking and --gpu <index> validation, and added unit tests for all of the above. Signed-off-by: Roman Sirokov <roman.sirokov@amd.com>
…back Address review feedback on PR #251: - resolve_gpu_indices now validates an explicit --gpu <index> against the DRM sysfs fallback's device count when amd-smi is unavailable, instead of only the amd-smi count. Previously an out-of-range index was silently accepted on a host with no amd-smi (sysfs works) and only failed later inside the engine. - read_drm_vram_usage no longer treats an unreadable mem_info_vram_used counter as 0 bytes used (which made the card look 100% free -- exactly what --gpu auto prefers first); it now skips that card instead. - read_drm_vram_usage withholds telemetry entirely when more than one AMD DRM card is present, since ascending card<N> order is only guaranteed to match HIP's compute-topology ordinal on a single-GPU host (an APU passes the same vendor + mem_info_vram_total filter as a discrete GPU, so an APU+dGPU host could previously feed a diverged ordinal into HIP_VISIBLE_DEVICES). - docs/vllm.md: corrected the fallback description, which only ever probes amd-smi (never rocm-smi) before falling back to DRM sysfs. Extracted the count-fallback logic into a new effective_gpu_count helper shared by --gpu auto ranking and --gpu <index> validation, and added unit tests for all of the above. Signed-off-by: Roman Sirokov <roman.sirokov@amd.com>
|
Round 2. Items 3 and 5 are genuinely fixed. Items 2 and 4 are fixed in intent, but the implementations leave a hole and add a new regression.
Smaller things:
Untested: the |
|
Thanks for the Round-2 review — pushed Multi-card guard counted surviving rows, not AMD cards found. Fixed.
The "rejects out-of-range index" test didn't call Body should name the declined scenario + its Gherkin reason. Done in the body: Smaller items: removed the dead sort/enumerate tail after the guard; |
|
Round 3. The multi-card guard (A), the dead sort/enumerate tail, Blockers
Nits (non-blocking)
|
|
Thanks for the Round-3 review — pushed Blocker 1 — the fallback reduced the usable set to a length. Fixed at the layer you named. The count bound is gone; Blocker 2 — the fallback branch wasn't injectable. Split the seam you asked for: Blocker 3 — scenario + gated lane in the body. Done in the PR body (not just this comment). The user-observable "explicit Nits. Fixed the two Verification note: the full |
rominf
left a comment
There was a problem hiding this comment.
This is a well-tested change and the core GPU-selection/validation logic (the amd-smi-independent membership check, the DRM sysfs fallback and its multi-card guard, the conditional OOM diagnosis) looks sound after the several rounds of review already visible on the thread. I only found one new issue, introduced in the latest commit while resolving a rebase conflict in the docs.
In docs/vllm.md, the "Explicitly, the workaround for an OOM on a shared card is:" example has a duplicated ```bash fence opener right before the example commands. As written, the block opens, immediately closes/reopens on the literal text, and the commands after it are no longer inside a fenced code block for the rest of that section (until the next ```` ) closes it) - so the example won't render as a code block. Please drop the duplicate line.
…RM guard Round-2 review follow-ups on the DRM sysfs GPU-selection fallback. - Validate an explicit --gpu <index> against the amd-smi list count or, when amd-smi is absent, the KFD/DRM authority behind usable_amd_gpu_indices() (pinned_index_bound) instead of the DRM VRAM-fallback row count. The row count withholds telemetry on multi-GPU hosts and shrinks on a transient counter-read failure, so borrowing it as a validation bound hard-rejected legitimate indices. VRAM rows stay scoped to --gpu auto ranking. - The multi-card ordinal-ambiguity guard now counts AMD cards *found* (before the telemetry filters) rather than surviving rows, so a second AMD card with an unreadable counter still trips the guard instead of mislabelling the survivor ordinal 0 (the APU+dGPU misattribution the guard exists to prevent). - drm_device_is_amd now matches on vendor id OR an amdgpu uevent DRIVER line, the same two-signal test as rocm_core::is_amdgpu_device, so the fallback probe and the count authority agree on what an AMD card is. - Drop the now-dead sort/enumerate tail in read_drm_vram_usage (at most one card survives the guard) and fix the stale doc comment. - Tests: exercise the real Index-arm delegate (resolve_pinned_gpu_index) and add a two-AMD-card-with-unreadable-counter regression; add pinned_index_bound coverage. - Docs: README and the assistant SKILL note the DRM sysfs VRAM fallback rather than presenting amd-smi as the only source. Signed-off-by: Roman Sirokov <roman.sirokov@amd.com>
…g (EAI-8060) (#290) * feat(diagnose): add vLLM out-of-memory failure mode to the catalog (EAI-8060) Add a keyword-scored OOM signature to the rocm-core diagnosis catalog and a matching print-only remediation recipe. The error covers two distinct faults (a tenancy collision with vLLM's fixed ~90% VRAM reservation, versus a model that genuinely does not fit), so the wording stays conditional: it never prescribes lowering --gpu-memory-utilization as the unconditional answer, and the verify step avoids the tenancy knob. Because an Examination carries no per-GPU VRAM or tenancy fields, the match is keyword-only and the checker is gated to Linux (vLLM is Linux/WSL-only). - diagnose.rs: KEYWORDS_VLLM_OOM table + check_16_vllm_oom (linux-only) - fix.rs: print-only fix-16-vllm-oom recipe; catalog count 15 -> 16 and AUTO-set assertion strengthened - engines/vllm: serve OOM hint points users at 'rocm diagnose --symptom' - e2e-cucumber: conditional-remediation scenario + step defs and catalog contract updated Signed-off-by: Roman Sirokov <roman.sirokov@amd.com> * fix(diagnose): require a vLLM anchor before matching the OOM checker Review feedback on #290 flagged that KEYWORDS_VLLM_OOM never required anything vLLM-specific: 'torch.OutOfMemoryError: CUDA out of memory' scores 45+45=90 (high confidence) under the keyword table alone, so any ROCm PyTorch job's OOM would be misreported as a vLLM startup OOM with rocm-serve-only remediation. gpu_memory_utilization -- the one vLLM-specific token -- was weighted lowest and never required. check_16_vllm_oom now requires an explicit vLLM anchor (the word 'vllm', or one of its distinctive flags: gpu[-_]memory[-_]utilization, tensor[-_]parallel) before the keyword table is scored at all. Update the serve OOM hint's suggested --symptom text and the matching e2e-cucumber step to carry that anchor so the self-referential 'rocm serve' -> 'rocm diagnose' flow keeps working, and add a regression test for the reported false positive. Also fix a second issue from the same review: the diagnose() WSL branch dropped sub-threshold hits from matched entirely when nothing cleared MIN_SCORE_FOR_MATCH, which the DiagnoseReport::matched doc says should never happen. It now keeps whatever run_all_checks returns (empty only when no wsl-applicable checker fired at all) and adds a regression test. Signed-off-by: Roman Sirokov <roman.sirokov@amd.com> * diagnose: drop the non-existent multi-GPU sharding remedy and tighten the vLLM OOM anchor Round-2 review (EAI-8060): - Remove the `--tensor-parallel-size` / multi-GPU sharding remediation from both the fix catalog (fix-16-vllm-oom) and the diagnose summary: the flag does not exist and rocm-cli serves one model on a single GPU (docs/vllm.md). The 'model does not fit' branch now points only at a smaller/quantized model. - Drop `tensor[-_]parallel` from VLLM_ANCHOR_PATTERN: it is a Megatron/DeepSpeed term, so anchoring on it would misattribute those frameworks' OOMs to vLLM. The anchor is now just `vllm|gpu[-_]memory[-_]utilization`. - Route the user's *actual* failing log line into the `rocm diagnose --symptom` hint (vllm-anchored) instead of a canned literal. - Escape the dot in the `torch\.outofmemoryerror` keyword regex and let the `gpu[-_]memory[-_]utilization` keyword accept a hyphen like the anchor. - Tests: e2e reads high_confidence_threshold from the report instead of a hardcoded 75, locks out `--tensor-parallel-size`, and shares a find_vllm_oom helper; the sub-threshold unit test uses `.expect()` instead of a vacuous `if let`. - docs/vllm.md and the @requires-bare-metal doc note the `rocm diagnose --symptom` pointer and the WSL keyword-only exception. Signed-off-by: Roman Sirokov <roman.sirokov@amd.com> * style: rustfmt the new OOM --symptom routing test assertion Signed-off-by: Roman Sirokov <roman.sirokov@amd.com> --------- Signed-off-by: Roman Sirokov <roman.sirokov@amd.com>
…gth (EAI-8058) When amd-smi is unavailable, `--gpu <index>` validation fell back to the *length* of usable_amd_gpu_indices(). That set holds absolute, unrenumbered ordinals after the visibility mask, so on a masked multi-GPU host (e.g. HIP_VISIBLE_DEVICES=2 on a 4-GPU box -> usable [2]) the length-1 bound rejected --gpu 2 (the sole usable device) and accepted a hidden --gpu 0. Replace the count bound with an injectable validate_pinned_gpu_index_against that prefers the amd-smi count and otherwise checks index membership in the usable set -- the same authority the engine device gate uses. The detected/usable seam makes both branches unit-testable without hardware. Also correct two docs/vllm.md inaccuracies (note timing; missing --engine vllm in the workaround examples). Signed-off-by: Roman Sirokov <roman.sirokov@amd.com>
A merge-conflict resolution left two consecutive ```bash fence openers before the shared-card OOM workaround example, so the block opened and immediately reopened on the literal text and the commands rendered outside a code block. Drop the duplicate opener so the example renders as a single fenced block. Signed-off-by: Roman Sirokov <roman.sirokov@amd.com>
59c7f31 to
e94ca5f
Compare
|
Thanks — good catch, the merge-conflict resolution had left two consecutive |
This pull request improves GPU selection and user guidance for ROCm and vLLM, especially in shared or containerized environments where the standard
amd-smitool may not be available. It adds a fallback for GPU VRAM telemetry, enhances user warnings and hints for out-of-memory (OOM) conditions, and ensures consistent messaging across CLI and engine surfaces. The changes also include comprehensive tests for the new logic.GPU selection and VRAM telemetry improvements:
/sys/class/drm/card*/device/mem_info_vram_{total,used}) whenamd-smiis not available, so--gpu autoranking and low-VRAM warnings still have telemetry on a single-AMD-GPU host without amd-smi. The fallback deliberately withholds telemetry on a host with more than one AMD DRM card, becausecard<N>numbering is not guaranteed to match HIP's device ordinal there — so it is a single-GPU convenience, not a multi-GPU replacement.--gpu <index>validation is amd-smi-independent and checks membership, not a count: whenamd-smiis unavailable it validates the index against the KFD/DRM usable set (rocm_core::usable_amd_gpu_indices— absolute ordinals after theHIP_VISIBLE_DEVICES/ROCR_VISIBLE_DEVICESmask), the same authority the engine device gate trusts. Validating against a length would hard-reject the sole usable device on a masked multi-GPU host (e.g.HIP_VISIBLE_DEVICES=2on a 4-GPU host → usable[2], where--gpu 2must pass and--gpu 0must be rejected). The DRM sysfs VRAM rows are never used as a--gpu <index>bound; they stay scoped to--gpu autoranking.validate_pinned_gpu_index_against, exercised via an injecteddetected/usableseam so both branches are covered without touching hardware).User guidance and warnings for vLLM:
VLLM_GPU_MEMORY_UTILIZATION_HINTfor the recommended workaround when running out of memory on a shared/busy GPU, ensuring CLI and engine logs use consistent wording.--gpu-memory-utilizationworkaround when vLLM is selected and the GPU is busy, both interactively and in the deployment summary.Documentation:
docs/vllm.mdto explain the behavior on shared/busy GPUs, the single-GPU-only telemetry fallback, and the recommended OOM workaround.Behavior coverage (e2e):
--gpu <index>that is not usable is rejected outright, never silently remapped to another device" is covered by the Gherkin scenario@id:serve-absent-gpu-index-rejected(Scenario 13 intests/e2e-cucumber/features/model_serving.feature). It is tagged@requires-gpu @requires-os:linux, so it runs only on the GPU hardware lanes (Strix Halo / Instinct), not the GitHub-hosted mock lane: on a no-GPU host the GPU-required pre-flight refuses with "no usable AMD GPU" before the index is ever validated, so the index-specific rejection can only be observed where a real device is present. The membership-vs-count refinement in this PR is additionally unit-tested on every lane byvalidate_pinned_gpu_index_falls_back_to_usable_set_membership.These improvements make GPU selection more robust in diverse environments and provide clear, actionable guidance to users encountering memory issues with vLLM.