Repository navigation
llama : fix K/V and recurrent state cleanup after failed restores - #27530
Conversation
375cbde to
f931b4d
Compare
|
@ggerganov |
f931b4d to
5313ec0
Compare
|
After rebasing this PR onto the latest upstream master, I have one question about a performance asymmetry that became apparent after #27991 was merged.
This does not affect correctness and only affects the restore-failure path, but fragmented state can cause many more backend writes during cleanup. Would you prefer that I:
I'm leaning toward (3) to keep the scope focused, although (1) would be a small local change. |
|
I will review the test cases myself, and update later. |
34ccdb4 to
1348cb0
Compare
|
I'd like to confirm one thing about the tests in this PR. The existing state-related tests mainly cover the normal save/load paths, so the failed-restore cleanup paths added in this PR are not exercised by the current CI. On the other hand, if I add this test to
I consider both out of scope for this PR, and I don't think adding per-architecture exclusions to I'd appreciate your guidance on how to handle the tests. |
|
Ideally, this test should be part of the |
|
Adding the regression test to 1. Missing
|
| @@ -3023,6 +3035,8 @@ class llama_io_read_device : public llama_io_read_i { | |||
| size_t buf_size = 0; | |||
| size_t size_read = 0; | |||
|
|
|||
| bool discarded = false; | |||
There was a problem hiding this comment.
Instead of this stateful flag for keeping track of discard(), can we simply clear the rinfos and the other data such that the destructor remains a noop.
There was a problem hiding this comment.
@ggerganov
Thank you, updated discard() to clear rinfos and the buffer state directly.
ggerganov
left a comment
There was a problem hiding this comment.
include the fixes needed for the test-save-load-state integration in this PR,
Let's try doing it this way - prefer to not introduce a new test binary for that yet.
1348cb0 to
e8fcf8f
Compare
|
@ggerganov For issue 2, when the recurrent part fails during a hybrid restore, only the attention part was left in its restored state, so the attention state is now cleared on failure. I would appreciate it if you could take another look when you have time. |
|
Thanks, looks good. Let's wait for #29133 to merge, rebase this PR and run CI to confirm all is good. |
e8fcf8f to
e8531db
Compare
|
removed |
|
@ggerganov However, this problem can occur in every composite memory class that restores its components sequentially, so fixing it class by class becomes whack-a-mole. It may be better to handle this at a common level rather than per class. |
|
With the If you have ideas how to solve this at a common level, we can explore. But I don't think we want so very complicated mechanism for this - should be something simple if possible at all. |
|
@CHIPMUNK-T0T I made some changes to the |
e8531db to
dd10bf3
Compare
|
Rebased onto the latest upstream, and updated Test 9 to the new results table. Test 9 does not apply to models without memory, since there is no state to restore. ctest 62/62 and Test output (rebased tree, 127 generated models)1. Single model without memory ( 2. I would appreciate it if you could take another look when you have time. |
|
The new test 9 exposed a latent HRM-Text issue that is normally hidden by reallocation. hrm.z_l_init is placed on the input layer, so the ggml_add() with the embeddings is assigned to a different backend depending on the batch size. The allocation from the reserve graph therefore does not cover the following small decodes, and GGML_SCHED_NO_REALLOC=ON turns the resulting reallocation into an abort. I'll document the exact location and cause and report it as a separate issue. |
…ml-org#27530) * llama : add discard for deferred state writes * llama : add tensor zeroing helper for backends without tensor memset * llama : clear K/V data after failed sequence restore * llama : clear recurrent state data after failed sequence restore * llama : simplify discard and restore cleanup * llama : report error when abnormal cell count is found in state_read_meta * llama : clear attention state on hybrid restore failure * tests : cover failed state restore cleanup * llama : clear MLA state on dsa restore failure * tests : update test for rebased test suite * llama : clarify comment in llama_memory_recurrent::state_read
…ml-org#27530) * llama : add discard for deferred state writes * llama : add tensor zeroing helper for backends without tensor memset * llama : clear K/V data after failed sequence restore * llama : clear recurrent state data after failed sequence restore * llama : simplify discard and restore cleanup * llama : report error when abnormal cell count is found in state_read_meta * llama : clear attention state on hybrid restore failure * tests : cover failed state restore cleanup * llama : clear MLA state on dsa restore failure * tests : update test for rebased test suite * llama : clarify comment in llama_memory_recurrent::state_read (cherry picked from commit 08618ff)
…ml-org#27530) * llama : add discard for deferred state writes * llama : add tensor zeroing helper for backends without tensor memset * llama : clear K/V data after failed sequence restore * llama : clear recurrent state data after failed sequence restore * llama : simplify discard and restore cleanup * llama : report error when abnormal cell count is found in state_read_meta * llama : clear attention state on hybrid restore failure * tests : cover failed state restore cleanup * llama : clear MLA state on dsa restore failure * tests : update test for rebased test suite * llama : clarify comment in llama_memory_recurrent::state_read (cherry picked from commit 08618ff)
…ml-org#27530) * llama : add discard for deferred state writes * llama : add tensor zeroing helper for backends without tensor memset * llama : clear K/V data after failed sequence restore * llama : clear recurrent state data after failed sequence restore * llama : simplify discard and restore cleanup * llama : report error when abnormal cell count is found in state_read_meta * llama : clear attention state on hybrid restore failure * tests : cover failed state restore cleanup * llama : clear MLA state on dsa restore failure * tests : update test for rebased test suite * llama : clarify comment in llama_memory_recurrent::state_read (cherry picked from commit 08618ff)
…genen Restores Mechanismus: Deferred IO-Reader (host + device) sammeln Tensor-Writes und flushen sie erst im Destruktor. Schlug ein Restore per Exception fehl, wurden die bereits gelesenen Teil-States trotzdem in die Tensoren geschrieben → halb-restorierter K/V- bzw. Recurrent-State → inkonsistente State-Reads/Writes → spaeterer CUDA-Abort (z.B. an der Prefill→Decode- Grenze, siehe Uranus-Qwen3.8-Crash und upstream ggml-org#23210). Fixes (cherry-picked from upstream 08618ff / llama.cpp ggml-org#27530): - llama_io_read_i::discard() — verwirft deferred tensor reads; beide state_*_set_data catch-Bloecke rufen es vor Rueckgabe von 0 - llama_clear_tensor_data() — Zeroing-Helper fuer Backends ohne memset - llama_kv_cache::state_clear() — zeroed die K/V-Daten der fehlgeschlagenen Restore-Zellen (spiegelt state_read_data-Schreibmuster inkl. TurboQuant- Padding via t->ne[0]); seq_rm allein reichte nicht, da freed cells von der Attention weiter lesbar sind - llama_memory_recurrent::state_clear() — gleiches fuer r_l/s_l-Ranges; meta_read-Flag merkt ob cell_head gueltig ist - try/catch um recr state_read_data — Exceptions fuehrten bisher an der Cleanup-Behandlung vorbei - llama_memory_hybrid::state_read + llama_kv_cache_dsa::state_read — try/catch-Rollback: schlaegt der zweite Sub-Reader fehl, wird der bereits restaurierte erste Teil via state_clear rueckgaengig gemacht - Bound-Guard in beiden state_read_meta: cell_count > cells.size()/size wird vor der Allokation abgelehnt ("abnormal cell count") Nicht uebernommen: tests/test-save-load-state.cpp — unser Test-Harness ist aelter als upstreams rebased Suite; Test 9-Port braucht dessen Infrastruktur. iswa-Wrapper unveraendert (upstream hat ihn ebenfalls nicht angefasst).
Review-Follow-up zu 41caa58 (Port von upstream ggml-org#27530): upstream hat die iSWA-Varianten nicht angefasst — gleiche Bug-Klasse, eigene Lücke. Mechanismus: wirft kv_swa->state_read (oder mem_recr->state_read in hybrid-iswa), bleibt kv_base (bzw. mem_attn) vollständig restauriert während der Restore insgesamt fehlschlägt → halb-restaurierter State. Upstream-Lücke, nicht Port-Fehler — betrifft Gemma-4 (iSWA-Produktion). - llama_kv_cache_iswa::state_clear(seq_id): cleart kv_base + kv_swa - kv_swa->state_read in try/catch → kv_base->state_clear + rethrow - llama_memory_hybrid_iswa::state_read: catch → mem_attn->state_clear - llama_kv_cache::state_clear: `other`-Guard (shared-Cells-Caches, spiegelt die Konvention von state_read)
Overview
A failed per-sequence state restore can remove sequence metadata while leaving K/V or recurrent-state tensor data written by the failed restore.
Buffer-backed restores can also leave deferred writes pending, allowing them to be applied after cleanup.
This PR contains failed restores by:
cell_countvalues before they are used for allocation or target-range setup;llama_memory_hybrid.Failures before modifying the target sequence leave it unchanged. After modification, the affected state is removed rather than attempting transactional rollback. For
llama_memory_hybrid, if the attention component has already been restored and the recurrent component then fails, the restored attention state is also cleared.Fixes #27068.
Additional information
The original issue was observed in the K/V cache, but the same failure-cleanup behavior is needed for recurrent memory.
Tensor cleanup is only performed after a valid target range has been established, so failures during metadata parsing do not clear unrelated cells.
Per-sequence restore now also validates
cell_countagainst the available cache or recurrent-memory capacity before using it.For
llama_memory_hybrid, restore is sequential across the attention and recurrent components. If the recurrent restore throws after the attention restore has succeeded, the attention state restored for that sequence is cleared before the exception is rethrown.The cleanup runs only on restore failure and does not affect successful restore or normal decoding.
Tests
Added failed-restore regression coverage to
test-save-load-state. Test 9 exercises corrupted buffer and file restores and runs through the existing architecture coverage, including hybrid models.The test verifies that a failed restore leaves the affected sequence empty and does not leave tensor data that changes the logits of another sequence.
Local validation:
ctest: 62/62 passed.dream,llada,llada-moe, andrnd1) do not have memory.CUDA validation and server-level fault injection with K/V and hybrid recurrent memory were also performed on an earlier base.
Non-goal
This does not provide transactional restore. If a failed restore has already modified the target sequence, its previous contents are not reconstructed.
Cross-component cleanup is handled for
llama_memory_hybrid, where attention restore can precede a failing recurrent restore. Equivalent cleanup for the other composite memory implementations (llama_kv_cache_iswa,llama_memory_hybrid_iswa,llama_kv_cache_dsa_iswa, andllama_kv_cache_msa) is not addressed by this PR.The separate ON_DEVICE pre-validation issue is tracked in #27439.
Requirements
I have read and agree with the contributing guidelines
AI usage disclosure: YES