Files
vLLM-4x-RTX-3090/patches/0053-e2_guards-draft-identity-and-draft-PLE-guard-report-.patch
T
MOVZX 777e910dd0 Initial commit
Signed-off-by: MOVZX <movzx@yahoo.com>
2026-10-15 01:01:52 +07:00

555 lines
24 KiB
Diff

From e5f6387064eadbeaba0ae923f0141ef9f638b9af Mon Sep 17 00:00:00 2001
From: halt95 <halt95@users.noreply.github.com>
Date: Wed, 23 Sep 2026 11:11:01 -0400
Subject: [PATCH 053/103] e2_guards: draft identity and draft PLE guard report
the drafter's own state
---
tests/v1/test_ple_pull_compile_profile.py | 234 ++++++++++++++++++++++
vllm/v1/e2_guards.py | 37 +++-
vllm/v1/worker/e2_identity.py | 150 ++++++++++++--
vllm/v1/worker/gpu_worker.py | 11 +-
4 files changed, 411 insertions(+), 21 deletions(-)
diff --git a/tests/v1/test_ple_pull_compile_profile.py b/tests/v1/test_ple_pull_compile_profile.py
index d19ec53..97f4e60 100644
--- a/tests/v1/test_ple_pull_compile_profile.py
+++ b/tests/v1/test_ple_pull_compile_profile.py
@@ -11,6 +11,7 @@ reading is shown to accept what the fork's guard rejects.
import ast
import os
+import re
from pathlib import Path
from types import SimpleNamespace
@@ -610,3 +611,236 @@ def test_nvidia_qwen4exp_ops_carry_no_pointer_like_int_params() -> None:
):
bad.append(f"{f.name}:{fn}({a.arg})")
assert not bad, f"pointer-like int op params (AOT-baking hazard): {bad}"
+
+
+# ------------------------------------------ the e2-identity draft line
+
+#: The startup smoke's anchored parser for the identity line.
+_IDENTITY_LINE = re.compile(
+ r"e2-identity\[(?P<tag>PP\d+_TP\d+)\]: ple_backend=(?P<backend>\S+) "
+ r"ple_method=(?P<method>\S+) ple_weight_dtype=(?P<dtype>\S+) "
+ r"breakable=(?P<brk>ON|OFF) "
+ r"compile_mode=(?P<cmode>\S+) cudagraph_mode=(?P<gmode>\S+) "
+ r"role=(?P<role>target|draft)\s*$"
+)
+
+
+def _compiled_draft(live: bool):
+ """A draft model whose only compile wrapper is live (or not)."""
+ import torch.nn as nn
+
+ from vllm.compilation.wrapper import TorchCompileWithNoGuardsWrapper
+
+ class _Wrapped(nn.Module, TorchCompileWithNoGuardsWrapper):
+ def __init__(self) -> None:
+ nn.Module.__init__(self)
+
+ inner = _Wrapped()
+ inner.do_not_compile = not live
+ inner.compilation_config = SimpleNamespace(mode=CompilationMode.VLLM_COMPILE)
+ outer = nn.Module()
+ outer.model = inner
+ return outer
+
+
+def _shared_config():
+ """The ONE engine CompilationConfig, as the drafter's holder carries it."""
+ return SimpleNamespace(
+ compilation_config=SimpleNamespace(
+ mode=CompilationMode.VLLM_COMPILE,
+ cudagraph_mode=CUDAGraphMode.FULL_AND_PIECEWISE,
+ )
+ )
+
+
+def _resolved_speculator(model, prefill, decode):
+ """V2 autoregressive / MTP speculator after init_cudagraph_manager."""
+ return SimpleNamespace(
+ model=model,
+ vllm_config=_shared_config(),
+ prefill_cudagraph_manager=(
+ None if prefill is None else SimpleNamespace(cudagraph_mode=prefill)
+ ),
+ decode_cudagraph_manager=(
+ None if decode is None else SimpleNamespace(cudagraph_mode=decode)
+ ),
+ )
+
+
+def _logged_identity(monkeypatch, fn, *args) -> list[str]:
+ from vllm.v1.worker import e2_identity
+
+ lines: list[str] = []
+ monkeypatch.setattr(e2_identity, "_rank_tag", lambda: "PP1_TP0")
+ monkeypatch.setattr(
+ e2_identity.logger, "info", lambda fmt, *a: lines.append(fmt % a)
+ )
+ monkeypatch.setattr(
+ e2_identity.logger, "warning", lambda fmt, *a: lines.append("WARN " + fmt % a)
+ )
+ fn(*args)
+ return lines
+
+
+def test_draft_identity_reports_the_drafters_resolved_graph_state(monkeypatch) -> None:
+ """The draft line read compile/cudagraph from the target's
+ shared VllmConfig (FULL_AND_PIECEWISE), while the V2 MTP speculator runs
+ prefill FULL_AND_PIECEWISE + decode FULL_DECODE_ONLY (the modes
+ e2-guard[runtime] logs). It must report the managers and the live wrapper,
+ in the smoke-anchored format."""
+ from vllm.v1.worker import e2_identity
+
+ runner = SimpleNamespace(
+ speculator=_resolved_speculator(
+ _compiled_draft(live=True),
+ CUDAGraphMode.FULL_AND_PIECEWISE,
+ CUDAGraphMode.FULL_DECODE_ONLY,
+ )
+ )
+ lines = _logged_identity(monkeypatch, e2_identity.log_draft_identity, runner)
+ assert len(lines) == 1, lines
+ m = _IDENTITY_LINE.search(lines[0])
+ assert m, lines[0]
+ assert m["role"] == "draft" and m["tag"] == "PP1_TP0"
+ assert m["cmode"] == "VLLM_COMPILE"
+ assert m["gmode"] == "prefill:FULL_AND_PIECEWISE,decode:FULL_DECODE_ONLY"
+ assert m["backend"] == m["method"] == m["dtype"] == "none"
+
+
+def test_draft_identity_compile_mode_is_the_live_wrapper(monkeypatch) -> None:
+ """Same shared config (VLLM_COMPILE); only the draft wrapper's liveness
+ differs -- the line must follow the wrapper, not the config."""
+ from vllm.v1.worker import e2_identity
+
+ runner = SimpleNamespace(
+ speculator=_resolved_speculator(
+ _compiled_draft(live=False),
+ CUDAGraphMode.FULL_AND_PIECEWISE,
+ CUDAGraphMode.FULL_DECODE_ONLY,
+ )
+ )
+ (line,) = _logged_identity(monkeypatch, e2_identity.log_draft_identity, runner)
+ m = _IDENTITY_LINE.search(line)
+ assert m and m["cmode"] == "NONE", line
+
+
+@pytest.mark.parametrize("shape", ["single", "unbuilt", "v1"])
+def test_draft_identity_other_speculator_shapes(monkeypatch, shape) -> None:
+ """Single-manager speculator -> bare mode; manager not built -> unresolved;
+ V1 drafter -> its dispatcher's mode. All still parse."""
+ from vllm.v1.worker import e2_identity
+
+ if shape == "single":
+ holder = SimpleNamespace(
+ model=_compiled_draft(live=True),
+ vllm_config=_shared_config(),
+ cudagraph_manager=SimpleNamespace(
+ cudagraph_mode=CUDAGraphMode.FULL_DECODE_ONLY
+ ),
+ )
+ runner, want = SimpleNamespace(speculator=holder), "FULL_DECODE_ONLY"
+ elif shape == "unbuilt":
+ holder = _resolved_speculator(_compiled_draft(live=True), None, None)
+ runner = SimpleNamespace(speculator=holder)
+ want = "prefill:unresolved,decode:unresolved"
+ else:
+ holder = SimpleNamespace(
+ model=_compiled_draft(live=True),
+ vllm_config=_shared_config(),
+ cudagraph_dispatcher=SimpleNamespace(
+ keys_initialized=True, cudagraph_mode=CUDAGraphMode.PIECEWISE
+ ),
+ )
+ runner, want = SimpleNamespace(drafter=holder), "PIECEWISE"
+ (line,) = _logged_identity(monkeypatch, e2_identity.log_draft_identity, runner)
+ m = _IDENTITY_LINE.search(line)
+ assert m and m["role"] == "draft" and m["gmode"] == want, line
+
+
+def test_target_line_at_load_draft_line_after_kv_init(monkeypatch) -> None:
+ """Load time logs the target line only (config level, unchanged); the
+ draft line is logged by log_draft_identity, which the worker calls after
+ initialize_kv_cache, where the drafter's managers are resolved."""
+ from vllm.v1.worker import e2_identity
+
+ runner = SimpleNamespace(
+ get_model=lambda: None,
+ speculator=_resolved_speculator(
+ _compiled_draft(live=True),
+ CUDAGraphMode.FULL_AND_PIECEWISE,
+ CUDAGraphMode.FULL_DECODE_ONLY,
+ ),
+ )
+ lines = _logged_identity(
+ monkeypatch, e2_identity.log_launch_identity, runner, _shared_config()
+ )
+ assert len(lines) == 1, lines
+ m = _IDENTITY_LINE.search(lines[0])
+ assert m and m["role"] == "target", lines
+ assert (m["cmode"], m["gmode"]) == ("VLLM_COMPILE", "FULL_AND_PIECEWISE")
+ # No drafter on this rank (not the last PP stage): no draft line, no warning.
+ assert (
+ _logged_identity(monkeypatch, e2_identity.log_draft_identity, SimpleNamespace())
+ == []
+ )
+ # The worker wiring: log_draft_identity follows initialize_kv_cache.
+ src = (REPO / "vllm/v1/worker/gpu_worker.py").read_text(encoding="utf-8")
+ body = src[src.index("def initialize_from_config") :]
+ body = body[: body.index("\n def ", 1)]
+ assert "log_draft_identity(self.model_runner)" in body
+ assert body.index("initialize_kv_cache(") < body.index(
+ "log_draft_identity(self.model_runner)"
+ )
+
+
+# ------------------------------------------ draft-role PLE layer ids
+
+
+def _ple_config(ids, *, num_hidden_layers=4, mtp_layers=1):
+ def text():
+ return SimpleNamespace(
+ ple_layer_ids=list(ids),
+ num_hidden_layers=num_hidden_layers,
+ mtp_num_hidden_layers=mtp_layers,
+ )
+
+ return SimpleNamespace(
+ engram_config=SimpleNamespace(cpu_offload=False),
+ model_config=SimpleNamespace(hf_text_config=text()),
+ speculative_config=SimpleNamespace(
+ draft_model_config=SimpleNamespace(hf_text_config=text())
+ ),
+ )
+
+
+def _ple_guard_ids(monkeypatch, config, role) -> str:
+ lines: list[str] = []
+ monkeypatch.setattr(
+ e2_guards.logger, "info", lambda fmt, *args: lines.append(fmt % args)
+ )
+ assert_ple_mode(config, role=role)
+ (line,) = lines
+ return line.rsplit("ple_layer_ids=", 1)[1]
+
+
+def test_draft_ple_guard_reports_the_drafters_own_ple_layers(monkeypatch) -> None:
+ """The reference host logged ple_layer_ids=[2] on the DRAFT guard
+ line -- the target's ids, read from the target's model_config. The MTP
+ drafter's layers (num_hidden_layers + i) carry no PLE block, so the draft
+ line must say []; the target line keeps [2]."""
+ monkeypatch.setenv(PULL_TRANSPORT_ENV, "1")
+ _clear_envs_cache()
+ cfg = _ple_config([2])
+ assert _ple_guard_ids(monkeypatch, cfg, "target") == "[2]."
+ assert _ple_guard_ids(monkeypatch, cfg, "draft") == "[]."
+
+
+def test_draft_ple_ids_follow_the_mtp_layer_range(monkeypatch) -> None:
+ """Discrimination: an id that DOES name an MTP layer (num_hidden_layers+1)
+ is reported on the draft line -- the rule is the drafter's own layers, not
+ 'always empty'. (Qwen4ExpTextConfig rejects such ids; this is a stand-in.)"""
+ monkeypatch.setenv(PULL_TRANSPORT_ENV, "1")
+ _clear_envs_cache()
+ cfg = _ple_config([2, 5], num_hidden_layers=4, mtp_layers=1)
+ assert _ple_guard_ids(monkeypatch, cfg, "draft") == "[5]."
+ assert _ple_guard_ids(monkeypatch, cfg, "target") == "[2, 5]."
diff --git a/vllm/v1/e2_guards.py b/vllm/v1/e2_guards.py
index 7624ae1..947dada 100644
--- a/vllm/v1/e2_guards.py
+++ b/vllm/v1/e2_guards.py
@@ -484,6 +484,38 @@ def resolve_ple_mode(vllm_config) -> str:
return PLE_MODE_UVA if cpu_offload else PLE_MODE_DEVICE
+def _role_ple_layer_ids(vllm_config, role: str) -> list[int]:
+ """The 1-based PLE layer ids the role's own decoder layers carry.
+
+ ``role="target"``: ``model_config.hf_text_config.ple_layer_ids``.
+ ``role="draft"``: the drafter is constructed with the target's VllmConfig
+ (the trap an earlier commit fixed for the architectures), so the target's
+ model_config names the TARGET's PLE layers. The drafter's decoder layers
+ are ``num_hidden_layers + i`` for ``i < mtp_num_hidden_layers``
+ (``Qwen4ExpMultiTokenPredictor``), and a layer builds a PLE block only if
+ ``layer_idx + 1`` is in ``ple_layer_ids`` (``Qwen4ExpDecoderLayer``). The
+ draft line reports exactly that intersection, read from
+ ``speculative_config.draft_model_config`` -- empty for this checkpoint,
+ whose ids must name backbone layers (``Qwen4ExpTextConfig``).
+ """
+ model_config = getattr(vllm_config, "model_config", None)
+ if role == "draft":
+ spec = getattr(vllm_config, "speculative_config", None)
+ draft_config = getattr(spec, "draft_model_config", None)
+ if draft_config is not None:
+ model_config = draft_config
+ text_config = getattr(model_config, "hf_text_config", None)
+ ids = list(getattr(text_config, "ple_layer_ids", None) or [])
+ if role != "draft":
+ return ids
+ num_hidden_layers = getattr(text_config, "num_hidden_layers", None)
+ if num_hidden_layers is None:
+ return ids
+ num_mtp = int(getattr(text_config, "mtp_num_hidden_layers", 1))
+ own = range(int(num_hidden_layers) + 1, int(num_hidden_layers) + num_mtp + 1)
+ return [layer_id for layer_id in ids if layer_id in own]
+
+
def assert_ple_mode(vllm_config, *, role: str = "target") -> str:
"""Startup guard: resolve, assert and log the effective PLE mode.
@@ -492,11 +524,10 @@ def assert_ple_mode(vllm_config, *, role: str = "target") -> str:
target's EngramConfig and the same process environment, so a mixed
configuration fails there too). NOT disabled by VLLM_E2_ALLOW_BREAKABLE:
that opt-out is about graph identity, not about owning the PLE table twice.
+ The logged ``ple_layer_ids`` are the role's own (:func:`_role_ple_layer_ids`).
"""
mode = resolve_ple_mode(vllm_config)
- model_config = getattr(vllm_config, "model_config", None)
- text_config = getattr(model_config, "hf_text_config", None)
- ple_layer_ids = list(getattr(text_config, "ple_layer_ids", None) or [])
+ ple_layer_ids = _role_ple_layer_ids(vllm_config, role)
engram_config = getattr(vllm_config, "engram_config", None)
logger.info(
"e2-guard[%s]: ple_mode=%s pull_transport=%d engram_cpu_offload=%s "
diff --git a/vllm/v1/worker/e2_identity.py b/vllm/v1/worker/e2_identity.py
index e457b09..e2a9527 100644
--- a/vllm/v1/worker/e2_identity.py
+++ b/vllm/v1/worker/e2_identity.py
@@ -9,8 +9,10 @@ GPU worker rank logs one line per model role it holds::
ple_weight_dtype=<dtype> breakable=<ON|OFF> compile_mode=<mode>
cudagraph_mode=<mode> role=<target|draft>
-(one line in the log). ``role=draft`` is logged only where a draft model is
-loaded (the last PP stage). Every value is read from the live objects:
+(one line in the log). ``role=target`` is logged after model loading;
+``role=draft`` is logged only where a draft model is loaded (the last PP
+stage), once the drafter's graph modes are resolved (after the KV cache is
+initialised -- see below). Every value is read from the live objects:
* ``ple_backend``: the class of each PLE layer's ``ple_embedding`` module, and
the transport that serves its rows on this rank, read from the placeholder's
@@ -25,8 +27,28 @@ loaded (the last PP stage). Every value is read from the live objects:
(``get_offload_output_dtype``).
* ``breakable``: ``is_breakable_cudagraph_enabled()``, the switch the capture
path itself reads.
-* ``compile_mode`` / ``cudagraph_mode``: the role's ``CompilationConfig``
- (config level, i.e. before KV-cache-time capture-mode resolution).
+* ``compile_mode`` / ``cudagraph_mode`` for ``role=target``: the engine's
+ ``CompilationConfig`` (config level, i.e. before KV-cache-time capture-mode
+ resolution).
+* ``compile_mode`` / ``cudagraph_mode`` for ``role=draft``: the DRAFTER's own
+ resolved state, not the config. The drafter is built with the target's
+ VllmConfig and there is one ``CompilationConfig`` in the engine, so the
+ config fields name the target's profile (the trap an earlier commit fixed for
+ the draft guard's architectures). What the drafter actually runs is:
+
+ - ``compile_mode``: the mode of the draft model's live
+ ``@support_torch_compile`` wrapper(s) (``do_not_compile`` false -- the
+ property the capture path tests, ``gpu/cudagraph_utils.py``
+ ``has_compiled_submodule``); ``NONE`` when no wrapper is live.
+ - ``cudagraph_mode``: the mode each speculator cudagraph manager holds after
+ ``init_cudagraph_manager`` (V2 runner): ``prefill:<m>,decode:<m>`` for the
+ autoregressive / MTP speculator, the bare mode for a single-manager
+ speculator; for a V1 drafter, its dispatcher's mode. These are the values
+ ``e2-guard[runtime]`` checks before capture. ``unresolved`` if a manager
+ does not exist yet.
+
+ Hence the draft line is logged from ``Worker.initialize_from_config`` after
+ ``initialize_kv_cache``, not at load time.
A role with no PLE layer reports ``none`` for the three PLE fields; several
distinct values on one rank are joined with ``,``.
@@ -102,46 +124,142 @@ def _rank_tag() -> str:
def _draft(model_runner: Any) -> tuple[nn.Module | None, Any]:
- """The loaded draft model and its config (V2 speculator or V1 drafter)."""
+ """The loaded draft model and its holder (V2 speculator or V1 drafter)."""
for name in ("speculator", "drafter"):
holder = getattr(model_runner, name, None)
model = getattr(holder, "model", None)
if isinstance(model, nn.Module):
- return model, getattr(holder, "vllm_config", None)
+ return model, holder
return None, None
+#: Written where a draft graph mode has no resolved source yet.
+UNRESOLVED = "unresolved"
+#: Speculator cudagraph-manager attributes (the set ``e2-guard[runtime]``
+#: reads), with the phase label each carries on the draft line.
+_DRAFT_MANAGER_PHASES = (
+ ("prefill_cudagraph_manager", "prefill"),
+ ("decode_cudagraph_manager", "decode"),
+ ("cudagraph_manager", None),
+)
+
+
+def _draft_compile_mode(model: nn.Module) -> str:
+ """Compile mode of the draft model's live ``@support_torch_compile`` wrappers.
+
+ ``NONE`` when no wrapper is live: the drafter then runs eager, whatever
+ the shared ``CompilationConfig.mode`` says.
+ """
+ from vllm.compilation.wrapper import TorchCompileWithNoGuardsWrapper
+
+ modes = {
+ _enum_name(getattr(getattr(m, "compilation_config", None), "mode", None))
+ for m in model.modules()
+ if isinstance(m, TorchCompileWithNoGuardsWrapper)
+ and not getattr(m, "do_not_compile", True)
+ }
+ return _join(modes) if modes else "NONE"
+
+
+def _draft_cudagraph_mode(holder: Any) -> str:
+ """The drafter's resolved cudagraph mode(s), read from its managers."""
+ parts = []
+ for attr, phase in _DRAFT_MANAGER_PHASES:
+ if not hasattr(holder, attr):
+ continue
+ manager = getattr(holder, attr)
+ mode = (
+ UNRESOLVED
+ if manager is None
+ else _enum_name(getattr(manager, "cudagraph_mode", None))
+ )
+ parts.append(mode if phase is None else f"{phase}:{mode}")
+ if parts:
+ return ",".join(parts)
+ # V1 drafter: one dispatcher, keyed in _check_and_update_cudagraph_mode.
+ dispatcher = getattr(holder, "cudagraph_dispatcher", None)
+ if dispatcher is not None and getattr(dispatcher, "keys_initialized", False):
+ return _enum_name(getattr(dispatcher, "cudagraph_mode", None))
+ return UNRESOLVED
+
+
def identity_line(
- tag: str, model: nn.Module | None, vllm_config: Any, role: str
+ tag: str,
+ model: nn.Module | None,
+ vllm_config: Any,
+ role: str,
+ *,
+ compile_mode: str | None = None,
+ cudagraph_mode: str | None = None,
) -> str:
+ """One identity line. ``compile_mode`` / ``cudagraph_mode`` override the
+ config-level values (the draft role passes its resolved state)."""
from vllm.compilation.breakable_cudagraph import is_breakable_cudagraph_enabled
embeddings = _ple_embeddings(model)
backends = {f"{type(e).__name__}@{_transport(e)}" for e in embeddings}
compilation = getattr(vllm_config, "compilation_config", None)
+ if compile_mode is None:
+ compile_mode = _enum_name(getattr(compilation, "mode", None))
+ if cudagraph_mode is None:
+ cudagraph_mode = _enum_name(getattr(compilation, "cudagraph_mode", None))
return (
f"e2-identity[{tag}]: "
f"ple_backend={_join(backends)} "
f"ple_method={_join({_method(e) for e in embeddings})} "
f"ple_weight_dtype={_join({_weight_dtype(e) for e in embeddings})} "
f"breakable={'ON' if is_breakable_cudagraph_enabled() else 'OFF'} "
- f"compile_mode={_enum_name(getattr(compilation, 'mode', None))} "
- f"cudagraph_mode={_enum_name(getattr(compilation, 'cudagraph_mode', None))} "
+ f"compile_mode={compile_mode} "
+ f"cudagraph_mode={cudagraph_mode} "
f"role={role}"
)
+def draft_identity_line(tag: str, draft_model: nn.Module, holder: Any) -> str:
+ """The ``role=draft`` line: PLE fields from the draft modules, graph fields
+ from the drafter's resolved state (never the shared CompilationConfig)."""
+ return identity_line(
+ tag,
+ draft_model,
+ getattr(holder, "vllm_config", None),
+ "draft",
+ compile_mode=_draft_compile_mode(draft_model),
+ cudagraph_mode=_draft_cudagraph_mode(holder),
+ )
+
+
def log_launch_identity(model_runner: Any, vllm_config: Any) -> None:
- """Log the identity line(s) for this rank. Never raises."""
+ """Log this rank's ``role=target`` line after model load. Never raises.
+
+ The ``role=draft`` line comes later, from :func:`log_draft_identity`, once
+ the drafter's graph modes exist.
+ """
+ tag = "PP?_TP?"
+ try:
+ tag = _rank_tag()
+ logger.info(
+ "%s", identity_line(tag, model_runner.get_model(), vllm_config, "target")
+ )
+ except Exception as error: # log-only: identity must never break a boot
+ logger.warning(
+ "e2-identity[%s]: unavailable (%s: %s)", tag, type(error).__name__, error
+ )
+
+
+def log_draft_identity(model_runner: Any) -> None:
+ """Log this rank's ``role=draft`` line, if it holds a drafter. Never raises.
+
+ Call after ``initialize_kv_cache``: that is where the V2 runner resolves
+ the target's mode and ``init_cudagraph_manager`` derives the drafter's
+ (and where the V1 runner keys the drafter's dispatcher).
+ """
tag = "PP?_TP?"
try:
+ draft_model, holder = _draft(model_runner)
+ if draft_model is None:
+ return
tag = _rank_tag()
- roles = [("target", model_runner.get_model(), vllm_config)]
- draft_model, draft_config = _draft(model_runner)
- if draft_model is not None:
- roles.append(("draft", draft_model, draft_config or vllm_config))
- for role, model, config in roles:
- logger.info("%s", identity_line(tag, model, config, role))
+ logger.info("%s", draft_identity_line(tag, draft_model, holder))
except Exception as error: # log-only: identity must never break a boot
logger.warning(
"e2-identity[%s]: unavailable (%s: %s)", tag, type(error).__name__, error
diff --git a/vllm/v1/worker/gpu_worker.py b/vllm/v1/worker/gpu_worker.py
index 4edfb76..8cb9d18 100644
--- a/vllm/v1/worker/gpu_worker.py
+++ b/vllm/v1/worker/gpu_worker.py
@@ -673,8 +673,9 @@ class Worker(WorkerBase):
model_runner = cast("GPUModelRunnerV2", self.model_runner)
model_runner._setup_ple_offload(self.parallel_config._ple_offload_ipc_path)
- # Log-only: this rank's PLE / capture identity for target and drafter,
- # read after the offload placeholders are armed (v1/worker/e2_identity.py).
+ # Log-only: this rank's PLE / capture identity for the target, read
+ # after the offload placeholders are armed (v1/worker/e2_identity.py).
+ # The drafter's line follows initialize_kv_cache (initialize_from_config).
from vllm.v1.worker.e2_identity import log_launch_identity
log_launch_identity(self.model_runner, self.vllm_config)
@@ -935,6 +936,12 @@ class Worker(WorkerBase):
),
)
+ # Log-only: the drafter's identity line, now that initialize_kv_cache
+ # has resolved its cudagraph managers (v1/worker/e2_identity.py).
+ from vllm.v1.worker.e2_identity import log_draft_identity
+
+ log_draft_identity(self.model_runner)
+
if self.model_config.enable_return_routed_experts:
self.model_runner.init_routed_experts_capturer()
--
2.43.0