Files
serverAppConfigs/scripts/patches/glm53-compile-05-workspace-acquisition-opaque.patch
T
Comrade Chief Designer d2e059262f frank-primary: patch 05 is not part of the confirmed blocker
Clarifies scope in the artifact header: torch.compiler.disable is itself a graph break,
so 05 helps only a hypothetical fullgraph=True route (where the workspace acquisition
would be better restructured out of the forward than made opaque). It is kept because
the discovery is real and the wrapper is a no-op when nothing is compiling, but it is
not required for the break-tolerant route whose only confirmed blocker is the dynamo
name-map KeyError.

Also verified in this pass: glm53-dflash-01-aux-hidden-states.patch applies cleanly to
the pinned image and reproduces its recorded patched sha256 (4ff6ff8d...), so all six
artifacts in scripts/patches are now apply-verified.
2026-09-30 16:27:24 -07:00

97 lines
4.8 KiB
Diff

# glm53-compile-05-workspace-acquisition-opaque.patch — the indexer's workspace
# acquisition must not be traced.
#
# STATUS: WIP — fifth of the "compile the GLM trunk" changelist. This is a break worth
# removing, but NOT part of the confirmed blocker and NOT required for the
# break-tolerant route: `torch.compiler.disable` is itself a graph break, so this patch
# helps only a hypothetical fullgraph=True route, where the workspace acquisition would
# be better RESTRUCTURED out of the forward (allocate at init/profile time) than made
# opaque. Kept because the discovery is real and the wrapper is a no-op when nothing is
# compiling.
#
# THE BREAK — CONFIRMED with AND WITHOUT the logging flag (2026-09-30):
#
# torch._dynamo.exc.Unsupported: Unsupported method call
# user stack
# glm5next/common/model.py:748 Glm5NextModel.forward
# glm5next/common/model.py:526 Glm5NextDecoderLayer.forward
# glm5next/common/attention.py:599 / :401
# glm5next/amd/sparse_indexer.py:711 forward_native
# glm5next/amd/sparse_indexer.py:132 sparse_attn_indexer_kpool
# v1/worker/workspace.py:135 get_simultaneous
# v1/worker/workspace.py:155 _ensure_workspace_size
#
# Line 132 is the PROFILE-RUN branch — the source comment says what it is:
#
# if not isinstance(attn_metadata, dict):
# # Reserve workspace for indexer during profiling run
#
# so the engine dies exactly where it sizes its memory. `_ensure_workspace_size`
# reads ContextVar and ubatch state (`_workspace_lane.get()`,
# `dbo_current_ubatch_id()`) and may allocate; none of that is traceable.
#
# FIX: the documented escape hatch — `torch.compiler.disable` around a thin wrapper,
# so dynamo stops analysing the call and executes it eagerly from inside the compiled
# region. Chosen over decorating the workspace manager's own methods because that
# would change workspace behaviour for every model, not just this one. The wrapper is
# a no-op when nothing is compiling, so it needs no env gate and is safe in the
# stock (uncompiled) path — which is why this patch can be reasoned about
# independently of whether the changelist ever ships.
#
# CAVEAT, stated plainly: a compiler-disabled region is still a graph break, so this
# needs patch 03 (VLLM_COMPILE_FULLGRAPH=0) to be tolerable at all, and whether dynamo
# can build a resume function around it is exactly what the next boot decides — the
# difference between this failure and 04's `Read uninitialized cell`.
#
# TARGET: vllm/models/glm5next/amd/sparse_indexer.py (inside the pinned image)
# base sha256 f773a99265d3f440c8fad22c8fb5a8b33f926162094cffc3a2ecdaa42763c5b1
# patched sha256 c154115afe8253a35c652b7198929ef4c1874957d333fdb3340cacf88e612b78
#
# APPLY: `patch -p1` from the vllm package root, or bind-mount over site-packages.
--- a/vllm/models/glm5next/amd/sparse_indexer.py
+++ b/vllm/models/glm5next/amd/sparse_indexer.py
@@ -35,6 +35,21 @@
from vllm.v1.attention.ops.common import pack_seq_triton, unpack_seq_triton
from vllm.v1.worker.workspace import current_workspace_manager
+@torch.compiler.disable
+def _acquire_workspace(*shapes_and_dtypes):
+ """Acquire shared workspace buffers, untraced.
+
+ Workspace acquisition reads ContextVar/ubatch state and may allocate
+ (v1/worker/workspace.py: ``_ensure_workspace_size`` -> ``_workspace_lane.get()``,
+ ``dbo_current_ubatch_id()``), which dynamo cannot trace -- it raises
+ ``Unsupported: Unsupported method call`` and kills the engine during the profile
+ run. ``torch.compiler.disable`` keeps the call as an opaque, eagerly-executed
+ region inside the compiled graph. No-op when not compiling.
+ """
+
+ return current_workspace_manager().get_simultaneous(*shapes_and_dtypes)
+
+
logger = init_logger(__name__)
# kpool write helper: form pools from the current token batch and compress them
@@ -129,7 +144,7 @@
values_spec, scales_spec = _gather_workspace_shapes(
total_seq_lens, head_dim, fp8_dtype, use_fp4_cache
)
- current_workspace_manager().get_simultaneous(
+ _acquire_workspace(
values_spec,
scales_spec,
((RADIX_TOPK_WORKSPACE_SIZE,), torch.uint8),
@@ -275,11 +290,10 @@
# Layout switches between FP8 (head_dim bytes + 4-byte fp32 scale) and
# MXFP4 (head_dim/2 bytes packed + head_dim/MXFP4_BLOCK_SIZE ue8m0
# scales) based on use_fp4_cache.
- workspace_manager = current_workspace_manager()
values_spec, scales_spec = _gather_workspace_shapes(
total_seq_lens, head_dim, fp8_dtype, use_fp4_cache
)
- k_quant_full, k_scale_full = workspace_manager.get_simultaneous(
+ k_quant_full, k_scale_full = _acquire_workspace(
values_spec,
scales_spec,
)