Skip to content

fix(io): bound EventPool free-list to avoid HSA signal exhaustion#491

Draft
AMD-yanfeiwang wants to merge 1 commit into
ROCm:mainfrom
AMD-yanfeiwang:fix/io-eventpool-hsa-signal-oor
Draft

fix(io): bound EventPool free-list to avoid HSA signal exhaustion#491
AMD-yanfeiwang wants to merge 1 commit into
ROCm:mainfrom
AMD-yanfeiwang:fix/io-eventpool-hsa-signal-oor

Conversation

@AMD-yanfeiwang

Copy link
Copy Markdown

Summary

EventPool (used by the fabric/xgmi IO backends) can grow its cached free-list without bound: GetEvent allocates a new hipEvent when the pool is empty, and PutEvent returned it with no cap. Under a bursty workload the free-list inflates to the concurrency peak and is never reclaimed, so the per-process HSA signal / KFD event budget can be exhausted — reported by the ROCm runtime as HSA_STATUS_ERROR_OUT_OF_RESOURCES on an unrelated queue op even though GPU memory is free.

Change

  • Add a per-device hard cap on the retained free-list (maxEventsPerDevice_, default max(8*numEvents, 512), never below numEvents).
  • PutEvent destroys surplus events above the cap instead of caching them, bounding the steady-state signal footprint. GetEvent still allocates on demand so callers always get a valid event.
  • No API break: the new constructor arg is optional/defaulted.

Test plan

  • Build mori; run MORI-IO fabric/xgmi transfer tests.
  • Soak a bursty transfer workload; confirm cached event count plateaus at the cap and no HSA_STATUS_ERROR_OUT_OF_RESOURCES.

Draft. Pairs with an sglang-side fix that pools the early-send CUDA events on the PD mori path.

EventPool::GetEvent creates a new hipEvent whenever the free-list is
empty and PutEvent pushed it back with no upper bound. Under a bursty
workload (e.g. PD KV-transfer under sustained load) the free-list grows
to the concurrency peak and is never reclaimed, so the per-process HSA
signal / KFD event budget can be exhausted. That surfaces as
HSA_STATUS_ERROR_OUT_OF_RESOURCES on an unrelated queue op even while GPU
memory is free.

Cap the retained free-list per device (default max(8*numEvents, 512),
never below numEvents); events returned above the cap are destroyed
instead of cached, keeping the steady-state signal footprint bounded.
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