# glm53-compile-03-fullgraph-optout.patch — let torch.compile split the graph instead # of failing on a break. # # STATUS: WIP — third of three patches in the "compile the GLM trunk" changelist. # With 01+02+03 the model TRACES, then hits the NEXT blocker (below). The set does not # yet boot the engine; nothing in scripts/ mounts it. # # THE BREAK: with 01+02 mounted the worker dies with # # RuntimeError: Graph breaks are not supported with aot compile. # Please use torch.compile(fullgraph=True). # # because vllm/compilation/wrapper.py calls torch.compile(..., fullgraph=True, ...) and # this build has AOT compile on by default (VLLM_USE_AOT_COMPILE). The GLM trunk cannot # satisfy fullgraph: its indexer metadata path syncs to the host — # models/glm5next/amd/sparse_indexer.py:263 int(positions[...].max().item()) + 1 # models/glm5next/amd/sparse_indexer.py:419 lmax = int(decode_metadata.decode_lens.max().item()) # — and a .item() inside a captured graph is not expressible. # # WHAT WAS VERIFIED (in-image, torch 2.11.0+rocm10.0, torch.compile(backend="eager")): # # fullgraph=True suppress_errors=False -> RAISE Unsupported # fullgraph=True suppress_errors=True -> RAISE Unsupported <-- suppress_errors # does NOT cover breaks # fullgraph=False suppress_errors=False -> ok (traceable segments compiled by # inductor, the rest runs eagerly; # numerics unchanged) # # So breaks must be TOLERATED, not suppressed: the traceable mass still fuses. This # patch makes the fullgraph requirement opt-out via VLLM_COMPILE_FULLGRAPH=0 (default 1, # so every other model keeps stock behaviour), and the run also needs # VLLM_USE_AOT_COMPILE=0 because AOT compile refuses breaks outright. # # TARGET: vllm/compilation/wrapper.py (inside the pinned image) # base sha256 969961dca41c78385212e985cfc0c57ef067f4a2d7490c73c658c600a1b95cac # patched sha256 732363bb1a1367772f13c60a655c678e7e2e9e56186677b14238f5e84cac31b3 # (the file already imports os; the patch does not add a second import) # # NEXT BLOCKER — NOT FIXED HERE. With 01+02+03 and # R4D_GLM_COMPILE=1 VLLM_COMPILE_FULLGRAPH=0 VLLM_USE_AOT_COMPILE=0 the trunk traces # ("Dynamo bytecode transform time: 1.08 s") and then the worker dies during profile_run: # # KeyError: 'in_proj_qkvbfg_a' # vllm/models/glm5next/common/model.py:456 in Glm5NextDecoderLayer.forward # # `in_proj_qkvbfg_a` is the KDA layer's merged column-parallel projection # (models/glm5next/common/kda.py:217, called at :407). The key is looked up in a # dict/mapping that the EAGER path never reaches, so compiling the trunk exposes a # latent bug in the mHC/KDA wiring rather than a dynamo limitation. Fix that and # whatever follows before this changelist can boot — then re-measure: the prize is the # 44 % pointwise mass (see 01), and the frozen-probe log line is the signal that 02 is # live. --- a/vllm/compilation/wrapper.py +++ b/vllm/compilation/wrapper.py @@ fullgraph opt-out (env VLLM_COMPILE_FULLGRAPH=0) @@ +# FORK-LOCAL (patch: fullgraph opt-out). torch.compile(fullgraph=True) turns any +# dynamo graph break into a hard failure; suppress_errors does NOT cover breaks +# (verified in-image, torch 2.11+rocm10.0). With VLLM_COMPILE_FULLGRAPH=0 the +# traceable segments are still compiled by inductor and the untraceable ones run +# eagerly, which is what a model with device-sync metadata (the GLM-5.3-Flash +# indexer) needs. Default 1 keeps stock behaviour for every other model. +_FULLGRAPH = os.environ.get("VLLM_COMPILE_FULLGRAPH", "1") == "1" - fullgraph=True, + fullgraph=_FULLGRAPH,