Skip to content

hip: stage large host->device copies through pinned memory - #39

Merged
charlie12345 merged 1 commit into
mainfrom
fix/hip-mmap-upload-stall
Jul 25, 2026
Merged

hip: stage large host->device copies through pinned memory#39
charlie12345 merged 1 commit into
mainfrom
fix/hip-mmap-upload-stall

Conversation

@charlie12345

Copy link
Copy Markdown
Owner

Fixes #37.

What happens

Loading a model with mmap enabled on the HIP backend can hang forever. ggml_backend_cuda_buffer_set_tensor hands pageable, file-backed pages straight from the mmap'ed GGUF to hipMemcpy. Once enough has been uploaded the ROCm SDMA path stops signalling completion and the runtime busy-waits in hsa_signal_wait, so the process pins one core at 100%, leaves the GPU idle, prints nothing and ignores SIGTERM (timeout N without --kill-after will not kill it).

Stack at the stall, from a gdb-launched run on gfx1151:

llama_model_base::load_tensors
  llama_model_loader::load_all_data
    ggml_backend_cuda_buffer_set_tensor
      hipMemcpySync
        rocr::hsa_signal_wait_scacquire
          rocr::core::BusyWaitSignal::WaitRelaxed   <-- spins forever

It is not a Laguna bug and not gfx1201 specific

#37 reports this against Laguna-S-2.1 on 3x R9700 (gfx1201). It reproduces on a single gfx1151 (Radeon 8060S, ROCm 7.14), and the model architecture is not the trigger:

case mmap result
Laguna-S-2.1 ROCmFP4 STRIX_LEAN, 58 GiB, HIP, -ngl 999 on hangs (killed after 92 min)
same file, same build, HIP off loads in 33 s, 35.4 t/s
same file, Vulkan on works
same file, HIP, -ngl 24 (~30 GiB uploaded) on works
same file, HIP, -ngl 40 on hangs
Laguna-XS-2.1 ROCmFP4, 16 GiB, HIP on works
Qwen3.6-35B-A3B ROCmFP4, 17 GiB, HIP on works

So it is upload volume on the HIP path, not the arch. The gqa-ratio backend bug mentioned in the upstream Laguna PR (ggml-org/llama.cpp#25165) is a red herring here: Laguna's ratios are 48/8 and 72/8, and FLASH_ATTN_EXT at nr2 6 and 9 passes on ROCm (this PR adds those cases to test-backend-ops).

The reason our own sweeps never caught this: every launcher under ~/launchers passes --no-mmap. Bare llama-bench / llama-server default to mmap on, which is what #37 hit.

The change

Route host->device copies of >= 1 MiB through a 32 MiB pinned bounce buffer so the DMA engine only ever sees resident pages. Falls back to the direct copy if the pinned allocation fails. Guarded by defined(GGML_USE_HIP); the CUDA path is untouched. Inference is unaffected — this is the load-time set_tensor path only.

Testing (gfx1151, ROCm 7.14)

  • The exact command from Eval bug: HIP inference hangs on gfx1201 w/ Laguna ROCmFP4 quants (related: #18) #37 now completes instead of hanging: llama-bench -dev ROCm0 -ngl 999 -fa 1 on Laguna-S-2.1 gives pp128 266.63 +/- 23.85, tg32 33.89 +/- 0.63 (mmap on). With mmap off: pp128 290.42, tg32 36.07.
  • Regression check with mmap on, HIP: Qwen3.6-35B-A3B ROCmFP4 pp128 928.47 / tg32 64.63; Laguna-XS-2.1 and Laguna-S-2.1 --no-mmap both still fine.
  • test-backend-ops -b ROCm0: no new failures. Two failures exist on this box before this change and were verified against unmodified main and a pre-Laguna binary: the norm.cu:425 GGML_ASSERT(nb00 == ts0) abort on non-contiguous NORM, and borderline ROPE_SET_ROWS q3_0/q6_0_rocmfpx precision misses.
  • scripts/check-rocmfp4-rocm-runtime-regression.sh fails marginally on this box both with and without this change (50.75-50.88 us/run with, 50.30 us/run baseline, threshold 50.00), i.e. pre-existing threshold tuning, not a regression from this PR.

Workaround for anyone on an affected build

Pass --no-mmap.

AI usage disclosure: root-cause analysis, the patch and this description were produced with Claude Code assistance; all repro runs and measurements above were executed on the gfx1151 box.

Loading a model with mmap enabled on the HIP backend can hang forever once
enough weight data has been uploaded. The copy in
ggml_backend_cuda_buffer_set_tensor sources pageable, file-backed pages
straight from the mmap'ed GGUF; past a certain volume in flight the ROCm
SDMA path stops signalling completion and the runtime busy-waits in
hsa_signal_wait, so the process pins one core at 100%, leaves the GPU idle,
prints nothing and ignores SIGTERM.

Reproduced on gfx1151 (Radeon 8060S, ROCm 7.14) with Laguna-S-2.1
Q4_0_ROCMFP4_STRIX_LEAN (58 GiB): stalls with -ngl 40 and -ngl 999, completes
with -ngl 24. Not model specific -- a 17 GiB Qwen3.6-35B-A3B and the 16 GiB
Laguna-XS-2.1 both load fine, and the same 58 GiB file loads fine on Vulkan
with mmap or on HIP with --no-mmap, which is why the sweeps here never caught
it (they all pass --no-mmap).

Route host->device copies of 1 MiB or more through a 32 MiB pinned bounce
buffer so the DMA engine only ever sees resident pages. Falls back to the
direct copy if the pinned allocation fails. HIP only; the CUDA path is
unchanged.

After this, llama-bench -dev ROCm0 -ngl 999 -fa 1 on that model reports
pp128 268.84 t/s / tg32 28.08 t/s instead of hanging.

Also cover Laguna's GQA ratios (48/8 and 72/8) in the flash-attention tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@charlie12345
charlie12345 merged commit 81d6fd0 into main Jul 25, 2026
29 of 44 checks passed
@charlie12345
charlie12345 deleted the fix/hip-mmap-upload-stall branch July 25, 2026 03:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Eval bug: HIP inference hangs on gfx1201 w/ Laguna ROCmFP4 quants (related: #18)

1 participant