@@ -110,3 +110,103 @@ def test_audited_and_broken_sets_stay_disjoint_for_fp8_source_entries():
110110 for wire in (WIRE_FP8_BLOCK128 , WIRE_MXFP8_G32 ):
111111 fmt = sp .FORMATS [wire ]
112112 assert not (fmt .audited_backends & set (fmt .known_broken_backends ))
113+
114+
115+ # --- A-side offset pre-warm: the CUDA-graph capture prerequisite ------------
116+ #
117+ # ``_SfOffsetCache.get`` computes offsets on the host and moves them with an
118+ # unpinned ``.to(device)``. Inside a CUDA graph capture that copy is a hard
119+ # error, so every key must already exist before capture starts. The B side was
120+ # always resolved at load from weight dimensions; the A side is keyed by the
121+ # runtime row count, which under FULL_DECODE_ONLY is first seen INSIDE the
122+ # capture region. These cover the reader and the pre-warm on CPU; the served
123+ # proof is a graph capture on the GPU image.
124+
125+ class _FakeExt :
126+ """Records the offset requests the lane makes."""
127+
128+ def __init__ (self ):
129+ self .calls = []
130+
131+ def mxfp8_sf_offsets (self , rows , k , is_b ):
132+ self .calls .append ((int (rows ), int (k ), bool (is_b )))
133+ return torch .zeros (4 , dtype = torch .int32 )
134+
135+
136+ def test_capture_sizes_reader_is_silent_without_vllm ():
137+ """No vLLM in the CPU tier: the reader must degrade to (), not raise --
138+ a load must never fail for a compilation-config schema reason."""
139+ from gridbook .mxfp8_dense_lane import _cudagraph_capture_sizes
140+ assert _cudagraph_capture_sizes () == ()
141+
142+
143+ def test_capture_sizes_reader_dedups_sorts_and_drops_nonpositive (monkeypatch ):
144+ """Exercise the REAL reader against a stub config.
145+
146+ ``monkeypatch.setitem`` on ``sys.modules`` is deliberate: it restores the
147+ entries afterwards, so this does not leak stub ``vllm`` modules into later
148+ files the way CONTRIBUTING.md warns about.
149+ """
150+ import sys
151+ import types
152+
153+ import gridbook .mxfp8_dense_lane as lane
154+
155+ config = types .SimpleNamespace (
156+ compilation_config = types .SimpleNamespace (
157+ cudagraph_capture_sizes = [8 , 2 , 2 , 0 , 4 , 1 , - 3 ]))
158+ stub = types .ModuleType ("vllm.config" )
159+ stub .get_current_vllm_config = lambda : config
160+ monkeypatch .setitem (sys .modules , "vllm" , types .ModuleType ("vllm" ))
161+ monkeypatch .setitem (sys .modules , "vllm.config" , stub )
162+
163+ assert lane ._cudagraph_capture_sizes () == (1 , 2 , 4 , 8 )
164+
165+
166+ def test_capture_sizes_reader_degrades_to_silence_on_a_hostile_config (
167+ monkeypatch ):
168+ """Schema drift must not fail a load -- the reason ops.py warns instead of
169+ raising. A config whose accessor explodes yields (), not an exception."""
170+ import sys
171+ import types
172+
173+ import gridbook .mxfp8_dense_lane as lane
174+
175+ def boom ():
176+ raise RuntimeError ("compilation_config moved again" )
177+
178+ stub = types .ModuleType ("vllm.config" )
179+ stub .get_current_vllm_config = boom
180+ monkeypatch .setitem (sys .modules , "vllm" , types .ModuleType ("vllm" ))
181+ monkeypatch .setitem (sys .modules , "vllm.config" , stub )
182+
183+ assert lane ._cudagraph_capture_sizes () == ()
184+
185+
186+ def test_prewarm_populates_a_side_for_every_capture_size (monkeypatch ):
187+ """The fix proper: one A-side entry per capture size, at the layer's K."""
188+ import gridbook .mxfp8_dense_lane as lane
189+
190+ monkeypatch .setattr (lane , "_OFFSETS" , lane ._SfOffsetCache ())
191+ monkeypatch .setattr (lane , "_cudagraph_capture_sizes" , lambda : (1 , 2 , 4 , 8 ))
192+ ext = _FakeExt ()
193+ lane ._prewarm_activation_offsets (ext , 4096 , torch .device ("cpu" ))
194+
195+ assert ext .calls == [(1 , 4096 , False ), (2 , 4096 , False ),
196+ (4 , 4096 , False ), (8 , 4096 , False )]
197+ # and a subsequent forward-time lookup is a cache HIT, i.e. no host copy
198+ # would be issued inside a capture
199+ before = len (ext .calls )
200+ lane ._OFFSETS .get (ext , 4 , 4096 , is_b = False , device = torch .device ("cpu" ))
201+ assert len (ext .calls ) == before
202+
203+
204+ def test_prewarm_is_a_noop_when_capture_sizes_are_unknown (monkeypatch ):
205+ """Eager serving (or an unreadable config) must not pay for this."""
206+ import gridbook .mxfp8_dense_lane as lane
207+
208+ monkeypatch .setattr (lane , "_OFFSETS" , lane ._SfOffsetCache ())
209+ monkeypatch .setattr (lane , "_cudagraph_capture_sizes" , tuple )
210+ ext = _FakeExt ()
211+ lane ._prewarm_activation_offsets (ext , 4096 , torch .device ("cpu" ))
212+ assert ext .calls == []
0 commit comments