GB10 TP3: DeepSeek V4.1 Flash export at 0572fd12 fails kernel tuning with a 0-byte scratch limit; 7.1-7.9 GiB available, below the 8 GiB floor

Aperta
#270 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
25/100
Tipo di issue
Bug
Chiarezza
Da chiarire
Stato di attività
Attiva
Stack tecnologico
python, pytorch

Direzione di ricerca

Start with _reserve_scratch and the declaration-tensor lifetime in ignition/preparation/tuning.py, then trace the listed per-decoder and per-layer allocation sites in ignition/recipes/deepseek41/ and components/. Compare those allocations with the reported memory measurements; the issue lists several possible directions but does not choose one. Done should include a defined fix for the zero-byte scratch-limit failure and evidence that the export completes without the reported memory shortfall.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

What happens

On three GB10 hosts (DGX Spark class, unified memory, one rank per host), an export of DeepSeek V4.1 Flash with tensor parallelism 3 at 0572fd12 stops 17.3 to 18.9 s into "Prepare and tune kernels" on every rank. Rank 0 runs python -m ignition export deepseek-v4.1-flash --ranks 3 --rendezvous <rank 0>:<port> --config <file>, and each peer runs python -m ignition join <rank 0>:<port> --rank <1|2> --ranks 3 --gpu 0 --config <file>. The file sets only [paths] kernel_cache and core_cache; everything else is a recipe default. Each rank reports:

b12x.preparation.types.CandidateResourceIneligibleError: no eligible configurations for moe.decode within the session scratch limit of 0 bytes

RecordedPreparationSession._reserve_scratch (ignition/preparation/tuning.py:387) bounds the scratch of kernel candidates with candidate_scratch_limit (ignition/preparation/host_memory.py:153). On an integrated GPU that limit is MemAvailable minus the greater of the 8 GiB floor (_HEADROOM_BYTES) and the plan's headroom (1 GiB here), minus 1 GiB of tuning growth and the persistent bytes of plans not yet materialized (envelope.pending_persistent_nbytes), clamped at zero; the minimum across ranks applies. With the limit configured as 0, the second requirements() call (tuning.py:434) reaches FlashInfer's candidate_memory_envelope, which raises because no moe.decode configuration fits. Both Ignition functions are the same at bbad44fe; what differs is the memory available at that point, measured below on bbad44fe plus #122.

MemAvailable was sampled every 2 s on each host. The comparison export is bf5ca911, the head of #122 from 10 to 12 November: one commit on bbad44fe, a preparation-only change that makes the 8 GiB floor a setting, run with --compile-headroom 6G; it completed. The setting changes the limit, not what is allocated before it. "Before graph catalog" is the last sample before the steep fall, which begins within one sample of the start of "Construct graph catalog" (phase starts are timestamped in the peers' logs and summed from phase durations on rank 0). "Tuning, before the reservation" is the samples from the start of "Prepare and tune kernels" to the scratch reservation (_reserve_scratch): at 0572fd12 to the failure, at bf5ca911 and f25a0386 to a 1.1 to 1.2 GiB step in MemAvailable 13 to 17 s after the phase start, taken as the arena allocation.

Export Rank Before graph catalog (MiB) Tuning, before the reservation (MiB)
0572fd12, default 0 19691 7314 to 7590
0572fd12, default 1 20350 7812 to 8083
0572fd12, default 2 20389 7756 to 7970
bf5ca911, 6 GiB 0 19644 11492 to 11588
bf5ca911, 6 GiB 1 20529 12012 to 12280
bf5ca911, 6 GiB 2 20531 12082 to 12195

Every host at 0572fd12 is below the 8192 MiB floor, so the limit is 0 whatever the pending bytes are; a limit above zero needs more than 9216 MiB plus those bytes, 1133 to 1902 MiB more than the hosts had. Each host has 3902 to 4468 MiB less available before the reservation at 0572fd12 than at bf5ca911. Swap use changed by at most 26 MiB on any host between the two columns.

At bbad44fe with the default floor, two exports on these hosts completed kernel tuning (4268.2 s and 404.2 s; #242 comment, #122 comment). Those reports give no MemAvailable at the reservation; at the 11492 to 11588 MiB of the lowest host at bf5ca911, the default floor leaves a limit of 2276 to 2372 MiB less the pending bytes.

Why it matters

With recipe defaults, an export at 0572fd12 stops at a point that two exports at bbad44fe passed on the same hosts, and the error reports a 0-byte limit without the memory found or required. The failure was observed in one export at 0572fd12; an export with the same ignition/ plus #122 reached the same memory level on rank 0's host (the --compile-headroom 4G export under "Possible direction"), and the shortfall exceeds the spread of the samples. #73 reports the same 8 GiB plus 1 GiB threshold stopping kernel tuning on GB10 for a GLM-5.3-Flash TP2 export with MTP; its 9,216 MiB MemoryError is the one tuning_limits raises.

Where the memory goes

When tuning starts, ranks 1 and 2 log the growth of torch.cuda.memory_allocated while each graph was constructed, summed by graph kind ("Graph operand allocation by operation", ignition/recipes/deepseek41/bootstrap.py, same code in both commits). The two ranks report the same bytes:

Graph kind bf5ca911 (MiB) 0572fd12 (MiB)
prefill 125.6 2665.6
speculative 2700.2 3434.2
vision 0.0 789.6
resume 7.0 85.7
decode 78.5 38.4
Total, with init, restore and snapshot 2911.4 7013.5

The per-kind rows do not compare, and the totals compare to within about 151 MiB. At bbad44fe one ScratchPool backed two GraphBufferPools (bootstrap.py:414-418) whose cursor each graph and prefill layer forked into overlapping storage, so a pool chunk is charged to the first graph that grows it, and the shared suffix and window-staging buffers (bootstrap.py:429, :432-434; 63 and 88 MiB in the table below) are allocated before the counter starts. The total is 4102 MiB larger at 0572fd12, about 3950 MiB after that offset; both are within the 3902 to 4468 MiB by which MemAvailable is lower before the reservation. The part of the fall that the logged growth does not cover is 5088 to 5619 MiB on every host in both commits, taking for rank 0 the growth that ranks 1 and 2 logged. When tuning started at 0572fd12, ranks 1 and 2 reported 9645 MiB allocated and 9666 MiB reserved, so cached free blocks held 21 MiB.

That pool was replaced by compiler-planned temporaries in 4a24d78a, merged through 2b38bf9d and e5e78818. 4a24d78a reports DeepSeek V4.1 on TP4 and states that "no matched serving-memory comparison was run". At 0572fd12 the example operands that operator declarations keep for tuning (declaration tensors) are alive across the reservation: finalizers registered through register_finalizer (tuning.py:746-753) release them after all tuning jobs (tuning.py:596-597), and the recipe's own releases (bootstrap.py:580-588) follow session.tune.

Allocation sites that are per decoder or per layer at 0572fd12 and came from the shared pool at bbad44fe, with sizes computed from tensor shapes in the code (10 prefill capacities in 2 modes, 64 packed verification shapes with a batch sum of 683, 40 layers), not measured:

Allocation at 0572fd12 0572fd12 (MiB) bbad44fe (MiB)
Verification window staging, one (40, batch, 136 × 528) byte buffer per verification decoder (components/ring_commit.py:60-64); bbad44fe shares one 1871 88
128-row suffix Scratch for each of 18 packed prefill decoders (recipes/deepseek41/decoder.py:263-264); bbad44fe shares one 1141 63
Compressor operands per KV-source layer and decoder (recipes/deepseek41/attention.py:151-167) 672 20
Prefill window cache per layer and decoder (attention.py:308-309) 456 2
Indexer packed queries per selector (components/mxfp4_indexer.py:62-65) 297 0.3
VisionScratch and PreparedVision operands per patch capacity (bootstrap.py:519-525) not sized not sized

Restricted to prefill decoders, the suffix, compressor, window cache and indexer sites compute to about 2485 MiB, of the 2666 MiB logged for prefill. Verification staging plus 76 MiB of compressor and indexer operands of verification decoders compute to 1947 MiB, of the 3434 MiB logged for speculative; the rest was not itemised.

Not measured

  • pending_persistent_nbytes at the reservation on either commit.
  • MemAvailable at this point at bbad44fe with the default floor.
  • Which tensors make up each graph kind's storage; the per-site sizes are computed from shapes.
  • Why MemAvailable falls a further 214 to 276 MiB on every host in the 17 s of tuning before the reservation at 0572fd12 (96 to 268 MiB at bf5ca911).
  • Whether the contents of the kernel cache change the scratch that tuning requires.
  • Other models, tensor-parallel widths and hosts.

Possible direction

  • Give the per-decoder and per-layer declarations above shared backing through declaration_tensor roles (ignition/preparation/examples.py). 07e94cae made that helper reuse one allocation per role across capacities because "Retaining separate declaration tensors for every graph capacity can exhaust device memory before tuning"; in this recipe it covers MXFP8 activation staging and MLA norm-quantization outputs, none of the sites above.
  • Release the declaration tensors that the reservation and candidate measurement do not use before the reservation, instead of after all tuning jobs.
  • Report the memory found and required when the limit is zero. tuning_limits already raises with both numbers (host_memory.py:185-187), but it runs after _reserve_scratch (tuning.py:512 against :503).

#122's --compile-headroom gets past the failure but leaves the host short of memory. With --compile-headroom 4G on f25a0386 (#122 on 0572fd12, ignition/ otherwise identical), rank 0's host had 7256 to 7483 MiB before the reservation, within about 110 MiB of the 7314 to 7590 MiB of the 0572fd12 export and against 11492 to 11588 MiB at bf5ca911. The export passed the reservation; those samples give a limit of 2136 to 2363 MiB less the pending bytes on that host. The floor is an input to the scratch limit, the tuning limits and compiler admission, not a level the host is held above: during kernel tuning that host fell to 3381 MiB available (56 of 2186 samples below 4096 MiB) and its swap use grew from 628 to 4456 MiB. That host also runs processes outside the export, and which pages moved to swap was not examined. An earlier 6 GiB export of bf5ca911, not the one in the table, spent 4271.5 s in kernel tuning and is reported in the #122 comment with a minimum of 7018 MiB on rank 0's host and swap growing from 374 to about 3000 MiB during kernel tuning; the two exports differ in floor and in kernels measured, so they do not isolate the effect of the graph operand storage. The 4 GiB export completed in 9527 s: kernel tuning took 4611.9 s, all 38 forwards compiled in 1848.1 s with one compiler worker per host, and the core was written. After kernel tuning that host's lowest sample was 6768 MiB, and its swap use peaked at 5609 MiB during compilation.

Environment

  • Three GB10 hosts (DGX Spark class, unified memory, MemTotal 121.6 GiB), one rank per host.
  • Checkpoint deepseek-ai/DeepSeek-V4.1-Flash-1017 (revision 1bae0e10), recipe defaults, compile_workers unset.
  • Page caches dropped before each export; MemAvailable 115.8 to 116.6 GiB before the start. The kernel cache directory held results of earlier bbad44fe-based exports. vm.min_free_kbytes is 45154 on rank 0's host.
  • 0572fd12 (failure), bf5ca911 with --compile-headroom 6G, f25a0386 with --compile-headroom 4G; FlashInfer as pinned by each tree (7b35510b at 0572fd12, 85ea6e76 at bbad44fe).
Lingua principale
Rust
Stelle
800
Fork
106
Merge medio
1g 3h
PR unite (30g)
100

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di NVIDIA/hyperflare-inference

Tutte le issue di NVIDIA/hyperflare-inference

Issue simili

Altre issue su Rust

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.