Skip to content

fix(umbp): pool the gather streams so the standalone server stops leaking them - #799

Merged
isytwu merged 1 commit into
mainfrom
fix/umbp-sa-gather-stream-pool
Oct 19, 2026
Merged

isytwu merged 1 commit into
mainfrom
fix/umbp-sa-gather-stream-pool

Conversation

@isytwu

@isytwu isytwu commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator

Change

The standalone server's HbmCopyEngine kept one non-blocking HIP stream per (thread, device) for the gather kernel and never destroyed it. The server calls Submit from gRPC's sync thread pool, which retires and spawns threads under load (a TP8 hour saw ~1,300 threads come and go), and every HIP stream holds ~6.4 MiB of device memory for its kernarg pool. Next to sglang at mem_fraction 0.9, the streams used up the remaining VRAM until hipStreamCreateWithFlags failed, and HIP 7.2 turns that failure into a segfault (HostQueue::terminate() calls Thread::Release() on a null virtual device: segfault at 8 ... in libamdhip64.so.7.2.70204). That is why only TP8 at high concurrency crashed.

Gather streams are now pooled per device and lent to one gather at a time, so a device holds as many streams as its peak number of concurrent gathers, and the descriptor staging is kept per stream instead of per thread. HbmCopyEngine::GatherStreamsCreated() exposes the count for the new test HbmCopyEngine.GatherStreamsOutliveTheirThreads: 16 short-lived threads, one gather each, at most one stream created (main fails it with 16 vs 1).

The null dereference on a failed stream creation is a clr bug and will be reported to ROCm separately.

Verification

  • TP8 Kimi-K3 c14 with the unfixed server: segfault ~15 min into the hour, after 661 streams (118 threads seen). With this change: the full hour on two nodes, 56 and 64 streams (7-8 per GPU) across 509 and 1,289 threads, no crash, no HIP errors.
  • test_transfer_engine and test_hbm_backend pass. test_umbp_pool_client_ranges gives the same per-case results as main (its remote cases need RDMA, which the test container lacks).

fix/umbp-sa-prewarm-queues builds on this branch and fixes the stalls the server then showed on amdgpu 6.16.

…king them

HbmCopyEngine created one HIP stream per (calling thread, device) for the gather
kernel and never destroyed it, and LaunchDeviceGather kept its descriptor
staging per thread the same way.  The standalone server calls Submit from
gRPC's sync server pool, which retires and spawns worker threads under load
(at Kimi-K3 TP8 c14 the median worker lived 2.5 s and did 10 copies), so the
streams grew without bound: 2370 after 37 minutes.  Every HIP stream holds
~6.4 MiB of device memory for its kernarg pool, and with sglang at
mem-fraction 0.9 the GPU filled up until hipStreamCreateWithFlags failed.  HIP
7.2.4 then segfaults in its own failure path (HostQueue::terminate() releases
a null virtual device), which is the "segfault at 8 ... in libamdhip64" that
killed the server.

The streams are now pooled per device and lent to one gather at a time, so
concurrent copies still run on separate streams but a device's pool only grows
to its peak number of concurrent gathers; the descriptor staging is kept per
stream, which the caller holds exclusively until it synchronizes.  A stream
whose synchronize failed is dropped, as before.

On the same workload (MI355X, ROCm 7.2.4) the unpatched server crashed after
15 minutes with 661 streams; with this change it served the full 3600 s window
with 56 streams (7 per GPU) after 655 worker threads had come and gone.

HbmCopyEngine::GatherStreamsCreated() lets a test assert the reuse; the new
GatherStreamsOutliveTheirThreads test submits gathers from 16 successive
threads and expects at most one new stream.
@isytwu
isytwu merged commit 8ae8156 into main Oct 19, 2026
13 of 15 checks passed
@isytwu
isytwu deleted the fix/umbp-sa-gather-stream-pool branch October 19, 2026 08:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant