Repository navigation
Conversation
refresh_ar() keeps ar_off_ current from the host residency table, and the verify graph is chosen with ar_on() (all_resident_ && !ar_off_), so a prompt loan, a VRAM shrink or an adaptive swap switches the window to the doorbell graph. The batch host paths tested the initialisation latch all_resident_ instead, so while experts were temporarily evicted they skipped the CPU pool servicing and the doorbell graph waited for flags nobody raised - the same stall shape as Niko1221#646 by another route. This requires all_resident_ and ar_off_ both true: the all-resident graph is in use (the default from 0.1.40), but prefill temporarily evicts experts. STRATA_VERIFY_ALL_RESIDENT=0 masks the defect, explaining why it was not seen earlier. Reproduce: with the all-resident graph in use, run a batch window while prefill has experts out of VRAM; the host services nothing and the window waits for its bounded guard. The eight-row reproducer measured pool calls 0 and a 105-107 ms guard release before, and 1 pool call with a 0.1-0.2 ms completion after. Operator verified on RTX PRO 6000 Blackwell, sm_120, CUDA 13.3, driver 616.92: reproducer exit 0 for both batch methods with and without eviction, resident_plan_parity and verify_parity 2/2, fused native IQ3_XXS prefill test, Release rebuild with 58 sm_120 cubins confirmed by cuobjdump.
fragtion
added a commit
to fragtion/StrataPool
that referenced
this pull request
Oct 6, 2026
…1#1101, Niko1221#1166, Niko1221#1163 (open, on 0.1.40.1) - Niko1221#1102 / Niko1221#1201: the batch host paths skip the per-layer service per window (ar_on), not per process: with a prompt loan or swap in flight an all-resident stage takes the doorbell graph and stalled (the watchdog's "no progress" in several chats). - Niko1221#1185: a window graph that finds no VRAM frees older batch slot layouts' graphs instead of failing. - Niko1221#1101: prefill Stager threads sleep instead of yield-spinning (they competed with the CPU pool). - Niko1221#1166: --host-core sibling / STRATA_HOST_CORE=sibling: the host thread on the first core's other hardware thread, interrupts left alone (hybrid Intel CPUs, both of our PCs). Opt-in. - Niko1221#1163: a conversation parked again keeps at most an eighth of each K/V buffer in reserve (was up to 16 MiB per buffer, 0.4-0.5 GB per conversation). Skipped: Niko1221#1107 (conflicts with the staged walk's stream-ahead; no measurement given), Niko1221#1181 (decode unchanged in its own measurement). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0157fjixQD2nRxvCvtXq66DD
Niko1221
pushed a commit
that referenced
this pull request
Oct 7, 2026
…process (#1118) A stage that was 100% resident at init takes the doorbell graph while a prompt loan/shrink/swap is in flight (ar_off_), and that graph waits on host doorbells the skipped service never raises: one GPU spins at 100% while the host sits in cudaStreamSynchronize, until the watchdog fires with the previous stage's stale label. Key the all-resident service skip in run_slot_rows, batch_poll and service off ar_on(), as run() already does. PR #1102 (win10ogod) is the same fix for run_slot_rows and batch_poll; this one also covers service(). Co-authored-by: win10ogod <jmes100010@gmail.com>
Owner
0xrjman
pushed a commit
to 0xrjman/Strata
that referenced
this pull request
Oct 7, 2026
…process (Niko1221#1118) A stage that was 100% resident at init takes the doorbell graph while a prompt loan/shrink/swap is in flight (ar_off_), and that graph waits on host doorbells the skipped service never raises: one GPU spins at 100% while the host sits in cudaStreamSynchronize, until the watchdog fires with the previous stage's stale label. Key the all-resident service skip in run_slot_rows, batch_poll and service off ar_on(), as run() already does. PR Niko1221#1102 (win10ogod) is the same fix for run_slot_rows and batch_poll; this one also covers service(). Co-authored-by: win10ogod <jmes100010@gmail.com>
This was referenced Oct 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
stage_batch()refreshes residency before every window (refresh_ar(),src/core/verify.cpp:2252), which maintainsar_off_: a prompt loan, a VRAM shrink or an adaptive swap marks some experts-1for a while, andverify.hpp:326-329documents that every window then runs the doorbell graph. The graph choice therefore usesar_on()=all_resident_ && !ar_off_(verify.hpp:331).The two batch host methods added by
affb999(#646) test the initialisation latchall_resident_instead:run_slot_rows()—src/core/verify.cpp:2356batch_poll()—src/core/verify.cpp:2526and:2531This is not theoretical: it deadlocks the engine in normal use. While a long prompt is being read, the prompt path lends its expert-cache slots to prefill, so
ar_off_becomes true and the doorbell graph is selected — but the host still skips the per-layer service loop, becauseall_resident_never changes.run_slot_rows()then blocks incudaStreamSynchronize(cs_)(:2362), the graph rings its first doorbell and waits for the host's plan, and neither side can move.Deadlock mechanism
read_part()(src/program/generate.cpp:8855) callsbatch_step()between prompt chunks while prefill holds borrowed slots.stage_batch()→refresh_ar()setsar_off_ = true; the selected graph needs host service.run_slot_rows():2356testsall_resident_, which is stilltruefrom initialisation → skips the service loop →cudaStreamSynchronize(cs_)at:2362.wait_flag_ge(m_flagA_, ring, cs)atsrc/core/verify.cpp:1257, withring = 1and A still zero (B is a later dependency).Neither
batch_fatalnor the decode-share budget can intervene: both are only checked afterbatch_step()returns.Minidump evidence (three occurrences, RTX PRO 6000 Blackwell, sm_120, Windows 11)
The engine's own stall watchdog writes every thread's stack before it halts the process. CDB recovered 38 threads in each dump; the three hosts are parked in the same place:
all_resident_ar_off_strata+0x110465nvcuda64!cuStreamSynchronizestrata+0x110465nvcuda64!cuStreamSynchronizestrata+0x110465nvcuda64!cuStreamSynchronizeThe two residency bytes are
01 01in every dump. The 15 pool workers wait inSleepConditionVariableSRW, consistent with the host never issuing their work. Strata has no matching PDB, so its frames were mapped through the release image's disassembly: the image timestamp, size and CodeView GUID/age match all three dumps.The matching engine log line is:
The GPU finishing in 20/18/18 ms once the watchdog releases the flags corroborates the missing handshake.
A/B verification on the same machine
Trigger conditions were kept present in both arms — the all-resident (zero-doorbell) graph initialised, and prefill borrowing its slots — deliberately without
--no-prefill-borrow, which would have removed the trigger."parallel": 8, 262144 contextno progress for 60 s during a request (reading the prompt (batched), done up to token 8192))Post-fix acceptance on the same server with the patch only (no environment workaround):
2, 3, 5, 7, 11reproduced identically twice, 228 / 286 tok/s, speculative drafts 12/12 acceptedTwo earlier readings this analysis corrects
VirtualLockor a memory touch, and the fault count is unchanged between the report's two 2-second samples. The printed commit figure is processPagefileUsage, not bytes currently in the page file. Earlier memory-pressure costs remain possible and are not addressed here.Verifier::diag()(src/core/verify.cpp:317) derives that label from the progress-stage string;stage_batch()resets A/B/served/sequence and updates the batch rows but leaves the sololast_pos0_field alone. The zero A/B values belong to the unserviced batch handshake, not to a previous completed window blocking the next chunk.The change
Three conditions, one file:
all_resident_→ar_on()at the sites above. It uses the same effective residency predicate the graph selection already uses, and only restores ordinary host servicing while experts are absent. The zero-doorbell fast path is untouched for the fully resident case.Other indefinite waits checked
Prefill staging waits (
prefill.cpp:387,391,429,441), issuer waits (:2040,2070) and join (:3213), PLE future/collection waits (:1848,ple_reader.cpp:491), CUDA stream/event waits, refill synchronisation and the input/checkpoint mutexes were each compared against the captured host call; none matches. The serial prompt-window path already refreshes residency and usesar_on()(verify.cpp:1689,1723). One rawall_resident_branch remains inservice()at:2730, but it belongs to the two-GPU pipelined path with a different graph-selection scheme — these single-GPU dumps do not establish a defect there, and it is left untouched.Not covered
Single NVIDIA GPU on Windows only. No multi-GPU or layer-split verification. The minidumps contain CPU stacks, so the GPU-side wait is identified from source and the reported flag state rather than from a captured kernel stack. Exact GPU instruction state and the earlier paging delays were not captured. Multi-chunk prompts beyond ~16k tokens and cancellation during admission were not separately exercised.