Skip to content

[Misc][PP] Log the KV cache memory of every worker and the SM70 indexer decode route of every stage - #1293

Open
Peuqui wants to merge 2 commits into
1CatAI:mainfrom
Peuqui:pr-pp-stage-logs
Open

Peuqui wants to merge 2 commits into
1CatAI:mainfrom
Peuqui:pr-pp-stage-logs

Conversation

@Peuqui

@Peuqui Peuqui commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

Purpose

Two log lines that only the first pipeline stage printed, so a pipeline-parallel deployment could not be read from its log.

  1. Available KV cache memory per worker (f1948ed). Each worker logs "Available KV cache memory: X GiB" with info_once, whose default scope "local" logs only on the first local rank, so on one node only stage 0 prints its figure. The KV pool is sized by the smallest worker, which is often another stage. The engine core now logs the figures it receives from all workers in one line. In a DeepSeek-V4-Flash PP5 boot (three Tesla V100 and two Quadro RTX 8000), the worker line said "Available KV cache memory: 8.47 GiB" (stage 0), while the new line reads "Available KV cache memory per worker: 8.47 GiB, 1.39 GiB, 1.39 GiB, 1.39 GiB, 0.50 GiB": the last stage limits the pool.
  2. SM70 indexer decode route (99524c6). The two "SM70 indexer decode: ..." lines in vllm/models/deepseek_v4/sm70/indexer.py use info_once with the default scope, so only stage 0 named its decode route. They now pass scope="process", as the prefill route lines of [Perf][SM70][DeepSeek-V4] Long-prefill indexer and sparse attention: vectorized epilogue, fused softmax, Turing scorer #1280 do. In the same boot (our fork, which has the prefill lines with scope="process" and the decode line without), the prefill route came from all five stages ("fused SM75 scorer on cuda:0", "Triton scorer on cuda:1" ... "fused SM75 scorer on cuda:4") and the decode route from stage 0 alone ("cuBLAS route on cuda:0").

Not a duplicate: I searched the open PRs for "Available KV cache memory", "KV cache memory per worker", info_once, scope="process" and "indexer decode route", and compared the changed files with those of all open PRs. Our own #1276 changes vllm/v1/engine/core.py elsewhere, and our #1280, #1282 and #1286 change other parts of indexer.py (the prefill routes); a merge with each gives no conflict.

AI assistance was used for this change. I reviewed every line and ran the tests below.

Test Plan

Native build of this branch in place (TORCH_CUDA_ARCH_LIST=7.0), then one pytest process per file:
python -m pytest tests/kernels/test_deepseek_v4_sm70_indexer.py tests/v1/engine/test_engine_core.py

pre-commit run --from-ref origin/main --to-ref HEAD; pre-commit run mypy-3.10 --hook-stage manual --all-files

The log lines were read in a DeepSeek-V4-Flash PP5 boot of our fork (production entry, 2026-10-28).

Path coverage

Path / provider Format Key conditions (shape, TP/EP, graph, capability) Expected selection / fallback Evidence (source / static / executed / measured) Unverified scope
EngineCore._initialize_kv_caches any KV cache memory determined by the workers (not for attention-free models or a preset KV budget) one extra info line naming every worker's figure measured: fork PP5 boot log (tests/v1/engine/test_engine_core.py needs model weights we do not have offline, see Test Result) multi-node: the line lists every worker of the executor, as determine_available_memory returns them
SM70 indexer decode route log DeepSeek-V4 sparse indexer any SM70-family stage one line per process instead of per node source; measured: the prefill lines with the same scope in the fork PP5 boot none

Acceleration and benchmark contract (required for performance changes)

  • Default enabled or opt-in: log lines only; no behaviour change.
  • Required CLI options and environment switches: none.
  • KV cache dtype used for the benchmark: n/a (no benchmark).
  • Wheel SHA or source commit: this branch on main 6aea01f (the tests ran with it on 9a33cee; the three later main commits [Perf][SM70][Scheduler] Piecewise graphs for short mixed prefills; keep the mixed budget off the graph regime #1290-[Perf][SM70][Distributed] Fused TP4 push all-reduce + Gemma RMSNorm for 16/24/32 verifier rows #1292 touch neither the changed files nor these tests); the log evidence from our fork (github.com/Peuqui/1Cat-vLLM, prod-v5 89ce1e7), which carries the KV line already.
  • PYTHONPATH, source overlays, or external native libraries used (write "none" if absent): none.
  • User-entry route-hit, speed, and output-quality evidence: n/a.
  • Existing kernel/backend registry and capability-rejection reasons: not touched.
  • Per-engine configuration and deprecated-variable compatibility: no setting added.
  • New/changed environment metadata and generated reference check: none.
  • Route snapshot command and intentional changed rows (write "none" for refactors): none.
  • SM70 registered variables / unregistered reads / model-parameter restrictions, before -> after: unchanged.

Test Result

On a Quadro RTX 8000 and on a Tesla V100: tests/kernels/test_deepseek_v4_sm70_indexer.py 26 passed. tests/v1/engine/test_engine_core.py: 10 failed, 1 skipped on both cards, the same test IDs on main 9a33cee with the same build (the tests load llava-hf/llava-1.5-7b-hf, whose weights are not on this machine, so EngineCore is not exercised here; the log line was read in the fork boot above).

pre-commit run --from-ref origin/main --to-ref HEAD: every hook passes except check-layering, which reports vllm/model_executor/layers/fused_moe/runner/moe_runner.py (platform coupling 37 -> 39), as on main 9a33cee; this PR does not touch that file. pre-commit run mypy-3.10 --hook-stage manual --all-files: the only errors are three arg-type errors in vllm/v1/attention/backends/flash_v100/runtime.py, which mypy reports on main as well in our environment and 1Cat's CI does not report; this PR does not touch that file.

🤖 Generated with Claude Code

Peuqui and others added 2 commits October 28, 2026 14:39
The pool is the minimum over the pipeline stages; rank 0 alone logs its figure, so
the stage that limits it could not be told from the log.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011k7FsBAcZ8Cw91wisiZxMf
Signed-off-by: Peuqui <43776522+Peuqui@users.noreply.github.com>
logger.info_once defaults to scope="local", which logs only on the first
local rank, so on one node with pipeline parallelism only stage 0 named
its decode route. In a DeepSeek-V4-Flash PP5 boot (three Tesla V100 and
two Quadro RTX 8000) the prefill route lines, which already pass
scope="process", came from all five stages and the decode route line
from stage 0 alone. Both decode route lines now pass scope="process".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Peuqui <43776522+Peuqui@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant