Repository navigation
CUDA: Recapture graph after memory pool flush - #26771
Conversation
77eb9cf to
449e758
Compare
|
Rebased on latest master, re-ran the reproducer against master and the fix branch, updated description and added some context on why recaptures jump to 118 from 5. |
|
Sorry for the long radio silence, I had taken a break from llama.cpp and am currently working through my backlog. If you are still interested in working on this I would suggest you change the implementation like this: extend |
Assisted-by: Claude Opus 5.5
449e758 to
4fd7022
Compare
|
No worries, thanks for getting back! I pushed the new implementation based on your suggestion, let me know what you think. I'm not entirely sure if the Buffer pool full path is needed, but it seems correct to me. You might notice that the pp512 numbers took a hit compared to the previous iteration, this is also true on |
JohannesGaessler
left a comment
There was a problem hiding this comment.
While reviewing this PR I realized that the way the legacy pool is being handled is causing issues with dangling pointers. So while this PR is fixing one issue there are likely to be more. To be clear: we should just merge this PR as-is and not make further changes.
Put this in a separate PR, please. |
…+ master ggml-org#26771) master's pool-flush graph invalidation still counts the old single graph->instance member, which ggml-org#30804 replaced with the instances vector
Overview
Clear CUDA graphs after the memory pool returns buffers to the driver to ensure they're recaptured, thus avoid writing to a stale pointer during replay from a captured graph leading to a page fault. Fixes #26738.
As far as I can tell, this has been a latent bug that the changes introduced in #22155 made possible to happen, but it hasn't surfaced as the combination of graphs being enabled, no VMM, no FA, MoE with partial CPU offload and enough fragmentation to trigger it is pretty obscure. On my setup, after #22254 in addition to no VMM, graphs were also enabled, thus it only needed to meet the last three conditions to fail.
Additional information
On the following hardware:
Intel i7-8700K
AMD RX Vega 56, gfx900, 8 GB HBM2 VRAM
32 GB DDR4 RAM
running on top of ROCm 7.2.4
and the following build options:
Without the fix applied, the following run:
where
MODELis ggml-org/gemma-4-26B-A4B-it-GGUF:Q4_0, fails with the following:With the fix applied, the same run completes, with the recapture visibly doing its job whenever the pool flushes (first flush below):
All 5 flushes in the run:
If I push it towards
-d 32768with the same configuration otherwise, it simply runs out of memory:Performance with the fix applied vs the previous
GGML_CUDA_DISABLE_GRAPHS=1workaround (same binary, env toggle only,-d 16384 -r 3):GGML_CUDA_DISABLE_GRAPHS=1so no regression from keeping graphs enabled.
ggml_cuda_pool_legstoresggml_backend_cuda_context & ctx. The pool is owned by the context throughunique_ptr, so the reference cannot outlive the context.Invalidation is done in two places:
clear_pool(). This is the flush that triggers Page fault at depth with -fa 0 and MoE expert offload on HIP #26738.free(), aftercudaFree. Frees a buffer that a captured graph can still use, which is the same bug class. It needs all 256 slots to be in use, and I couldn't find a way to trigger this path, so this has not been tested in practice, though I believe it to be correct.The graphs are invalidated per context, so the global over-invalidation across devices from the initial counter-based implementation is gone.
This is reproducible on similar Nvidia hardware with
GGML_CUDA_NO_VMM=1set to ensure the legacy pool implementation is used, although I can't verify it myself.The contributing guidelines say a regression test should be added, but I'm not exactly sure if one can be implemented for this.
Requirements