[ROCm][VMM] Selective copy-vs-remap for small command-buffer slices + auto threshold#925
Closed
phambinhfin wants to merge 2 commits into
Closed
[ROCm][VMM] Selective copy-vs-remap for small command-buffer slices + auto threshold#925phambinhfin wants to merge 2 commits into
phambinhfin wants to merge 2 commits into
Conversation
…dow instead of VA-remapping Adds an opt-in size threshold (env XLA_VMM_TMP_COPY_THRESHOLD, bytes; 0 = disabled = current behavior) for the command-buffer VA remapping path. Slices whose size is <= threshold (the tiny scale/scalar/metric buffers that churn addresses every step) are excluded from the VA reservation and instead given a stable shadow device buffer whose address is baked into the command buffer once. Each step the slice is refreshed with a bidirectional device-to-device copy on the execution stream: real->shadow before execution (fresh inputs) and shadow->real after execution (propagate output scalars such as loss/token-count back to the buffers the host reads). This avoids the expensive hipMemUnmap/hipMemMap/hipMemSetAccess round-trip (which serializes across peer devices on ROCm) for those small buffers, while large slices still remap. This is the "balanced copy vs remap" idea discussed with the NVIDIA reviewer. llama2_7b, FSDP=8, 8xMI300X, coll_vmm leg (30 steps), loss matches baseline: threshold=0 : 132 ms (remap all) threshold=256B : 120 ms threshold=4096B : 121 ms threshold=65536B: 122 ms
…sized to free HBM
Turn XLA_VMM_TMP_COPY_THRESHOLD into a 3-way control:
0 -> disabled: remap every command-buffer slice (original behavior)
1 -> auto: derive the byte cutoff from this device's HBM bandwidth and
capacity AND the memory currently free (via DeviceMemoryUsage), so the
stable shadow pool is always guaranteed to fit (no searching, no OOM)
>1 -> force that exact byte cutoff (explicit override / sweeps)
The auto path admits the smallest slices first while bounding (a) per-slice copy
time, (b) aggregate per-step copy time, and (c) the shadow footprint by a
fraction of currently-free HBM. Large tensors keep stable addresses across steps
(their remap is already skipped/free), so they stay on the remap path; only the
tiny churning scalar/scale/metric slices are copied into a stable shadow.
ROCm-only: the entire path is gated on DeviceAddressVmmAllocator, so on NVIDIA
the cast is null, ExecuteThunksWithVaRemapping is never entered, and the env var
has no effect. NVIDIA behavior is unchanged.
Collaborator
Author
|
Superseded by #926 (same change, head branch renamed to phambinh/balance_vmm). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Dependency (read first)
This PR stacks on top of the ROCm VMM allocator work (branch
phambinh/rocm-vmm-allocator) and must merge after it. The base of this PR is intentionally set to that branch, notmain, so the diff here is only this change (xla/service/gpu/gpu_executable.cc). GitHub will auto-retarget tomainonce the VMM allocator PR lands.It is entirely ROCm-only and does not affect NVIDIA. The whole code path lives inside
ExecuteThunksWithVaRemapping, which is gated on:On NVIDIA the active allocator is the standard BFC/stream-executor allocator, so the cast is
null,use_command_buffer_va_remappingisfalse, the function is never entered, and theXLA_VMM_TMP_COPY_THRESHOLDenv var has no effect. NVIDIA code paths, defaults, and behavior are unchanged.Optimization
With the VMM command-buffer VA-remapping path, every command-buffer slice whose physical allocation churns each step is re-mapped via
hipMemUnmap/hipMemMap/SetAccess. For the tiny scalar / scale / metric buffers that churn every step, that driver round-trip dominates and serializes across peer devices. Large tensors, by contrast, keep stable addresses across steps, so their remap is already skipped (free).This change keeps those small churning slices in a stable shadow buffer (a fixed address baked into the command buffer once) and refreshes them with a cheap device-to-device copy each step (copy-in before exec, copy-back after, so output scalars like loss/metrics propagate correctly). Large slices stay on the remap path.
The size cutoff is chosen automatically — no manual tuning, no searching — via
XLA_VMM_TMP_COPY_THRESHOLD:01DeviceMemoryUsage)>1The auto selector admits the smallest slices first while bounding (a) per-slice copy time, (b) aggregate per-step copy time, and (c) the shadow footprint at a fraction of free HBM — so the shadow pool is always guaranteed to fit and never risks OOM. Default (unset) is auto.
Benchmarks (MI300X x8, llama @ 8 layers / 30 steps, median of steps ≥3)
auto + collective leg (
coll_vmm), disabled vs auto — all models=0)=1)The saving is a roughly fixed per-step cost (~6-13 ms; the work removed is the remap of the small churning slices, whose count is set by command-buffer structure, not model size). It therefore shows up as a larger percentage on short-step models and a smaller one on heavy models, but it is always a net win and never regresses.
autolands on the same optimum as a hand-tuned fixed 4 KB cutoff (llama2_7b: auto 121 ms == fixed-4K 120 ms).vmm leg (no collectives), disabled vs auto — same pattern
=0)=1)Correctness across every run: identical loss vs the disabled baseline and zero unmap errors.
Notes
[EXPERIMENT]— behind an env knob, default auto, ROCm-gated.