Coverage for / home / jenkins / .local / lib / python3.10 / site-packages / hyper_parallel / distributed / context_parallel / wrappers.py: 45%
450 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-11-15 07:18 +0800
« prev ^ index » next coverage.py v7.13.1, created at 2026-11-15 07:18 +0800
1# Copyright 2025-2026 Huawei Technologies Co., Ltd
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ============================================================================
15"""context_parallel.wrappers: built-in CP-aware inner attention wrappers (public, explicit injection).
17Since the explicit-injection rework the framework NEVER picks a CP wrapper
18automatically: the built-ins below are referenced explicitly — by
19registry name in an internal plan, by callable, or by a public forward
20replacement pointing at one of these functions:
22.. code-block:: yaml
24 plan_overrides:
25 - match: "*.self_attn.forward"
26 when: cp
27 replace:
28 kind: method
29 implementation: hyper_parallel.distributed.context_parallel.wrappers.sdpa_hf_cp_wrapper
31Wrapper contract (also the Target factory contract — at apply time the
32Target is built with its declared context, filled by name)::
34 @inner_wrapper
35 fn(target_module, mesh, tp_mesh, cp_mesh, ep_mesh, <configured params...>)
37The ``@inner_wrapper`` decorator is MANDATORY (injection discipline,
38see recipe_spec.py): the mesh family (``mesh``/``tp_mesh``/``cp_mesh``/
39``ep_mesh``) plus the anchor ``target_module`` are REQUIRED context
40params, ALL filled by the framework at apply time (None for inactive
41axes) — the user just uses them.
42Undecorated wrappers fail fast in the resolution chain; *args/**kwargs
43are forbidden. In-repo wrappers RETURN the replacement — a forward
44callable or _ForwardRewriteRequest(s) — and the forward rewriter
45validates, installs and rolls back (05 §15.2.3: module.forward is
46assigned only by distributed/_builder/forward_rewriter.py); external
47wrappers may still replace ``target_module.forward`` in place and return
48None. The replaced forward must accept the original forward's params
49(validated at apply time).
51- ``sdpa_qkv_cp_wrapper``: NeMo convention ``forward(q, k, v, ...)`` — explicit
52 K/V all-gather + D-04 offset-aware causal mask (fixes the is_causal
53 alignment error under CP);
54- ``sdpa_hf_cp_wrapper``: HF convention ``forward(hidden_states, ...)`` —
55 primitive interception of ``F.scaled_dot_product_attention`` (reuses HF
56 projections/RoPE), with misfire detection (raises if no call is
57 intercepted);
58- ``flex_qkv_cp_wrapper`` / ``flex_hf_cp_wrapper``: the two isomorphic
59 FlexAttention entries (block_mask must be built for the global kv length).
60- ``*_ulysses_cp_wrapper``: Pure Ulysses variants that exchange Q/K/V from
61 sequence shards to head shards before attention and restore the local
62 sequence shard afterward.
63- ``*_hybrid_cp_wrapper``: local-tensor Hybrid variants that run Ulysses
64 all-to-all inside each subgroup and K/V all-gather across the complementary
65 Colossal subgroup.
66- ``sdpa_*_load_balance_cp_wrapper``: local-tensor Colossal Head-Tail variants
67 for Q exchange, K/V all-gather, dual SDPA execution, output restoration,
68 and backward communication.
69- ``gdn_ulysses_cp_wrapper``: primitive interception for Gated DeltaNet,
70 with a causal-Conv1d halo and Ulysses exchange around the
71 Gated Delta Rule interface.
73Users may register their own named schemes::
75 INNER_WRAPPER_REGISTRY["my_flash"] = my_fn
77after which ``spec.inner_wrapper="my_flash"`` references it by name.
79The ``is_*_attention`` helpers are public utilities for authors of custom
80wrappers (choosing a scheme programmatically); the framework itself no
81longer dispatches heuristically on them.
82"""
84import functools
85import importlib
86import inspect
87import logging
88from typing import Any, Callable
90import torch # pylint: disable=forbidden-backend-import
91import torch.nn.functional as F
92from torch.nn import Module
94from hyper_parallel.distributed._builder.forward_rewriter import (
95 _ForwardRewriteRequest,
96)
97from hyper_parallel.distributed.context_parallel.collectives import (
98 _build_hybrid_cp_submeshes,
99 _ULYSSES_WRAPPED_FLAG,
100 _UlyssesContext,
101 _slice_sequence,
102 _validate_ulysses_head_counts,
103 flex_cp_allgather,
104 hybrid_cp_attention,
105 ulysses_head_to_seq,
106 ulysses_seq_to_head,
107)
108from hyper_parallel.distributed.context_parallel.attention import (
109 _cp_offset_causal_mask,
110 _dsa_cp_alltoall,
111 _mla_cp_alltoall,
112 _mome_cp_halo_exchange,
113 head_tail_load_balance_attention,
114)
115from hyper_parallel.distributed.context_parallel.gated_delta_net import install_gdn_ulysses_cp
116from hyper_parallel.distributed.recipe_spec import (
117 inner_wrapper,
118)
120logger = logging.getLogger(__name__)
123# ────────────────────────────────────────────────────────────────────────────
124# Style-detection helpers (public utilities for custom wrapper authors)
125# ────────────────────────────────────────────────────────────────────────────
127def _attn_implementation(module):
128 cfg = getattr(module, "config", None)
129 impl = getattr(cfg, "_attn_implementation", None)
130 if impl is None and isinstance(cfg, dict):
131 impl = cfg.get("attn_implementation")
132 return impl
135def is_sdpa_attention(module: Any) -> bool:
136 """True when the module is configured for or named as SDPA attention."""
137 impl = _attn_implementation(module)
138 return (impl == "sdpa") or ("SdpaAttention" in type(module).__name__)
141def is_flex_attention(module: Any) -> bool:
142 """True when the module is configured for or named as FlexAttention."""
143 impl = _attn_implementation(module)
144 return (impl == "flex_attention") or ("FlexAttention" in type(module).__name__)
147def is_hf_style_attention(module: Any) -> bool:
148 """HF style (forward(hidden_states,...), projections inside forward) -> the primitive-interception path."""
149 has_proj = (hasattr(module, "q_proj") and hasattr(module, "k_proj")
150 and hasattr(module, "v_proj"))
151 if not has_proj:
152 return False
153 try:
154 sig = inspect.signature(module.forward)
155 first_param = next(iter(sig.parameters.values()), None)
156 return first_param is not None and first_param.name == "hidden_states"
157 except (ValueError, TypeError):
158 return type(module).__name__.endswith("Attention")
161# ────────────────────────────────────────────────────────────────────────────
162# CP-aware SDPA core (K/V all-gather + D-04 offset causal mask)
163# ────────────────────────────────────────────────────────────────────────────
165def _prepare_cp_sdpa_kwargs(
166 kwargs: dict[str, Any], *, q_len: int, kv_len: int,
167 query_offset: int, device: Any) -> dict[str, Any]:
168 """Adapt a complete SDPA mask to one CP-local query interval."""
169 call_kwargs = dict(kwargs)
170 attention_mask = call_kwargs.get("attn_mask")
171 if attention_mask is not None:
172 if not isinstance(attention_mask, torch.Tensor):
173 raise TypeError(
174 "CP SDPA attn_mask must be a Tensor or None, got "
175 f"{type(attention_mask).__name__}"
176 )
177 if attention_mask.ndim < 2:
178 raise ValueError(
179 "CP SDPA attn_mask must expose query and KV dimensions, got "
180 f"shape {tuple(attention_mask.shape)}"
181 )
182 if attention_mask.shape[-1] != kv_len:
183 raise ValueError(
184 "CP SDPA attn_mask must cover the complete KV sequence: "
185 f"mask KV length={attention_mask.shape[-1]}, expected {kv_len}"
186 )
187 mask_q_len = attention_mask.shape[-2]
188 if mask_q_len != q_len:
189 if mask_q_len < query_offset + q_len:
190 raise ValueError(
191 "CP SDPA attn_mask does not cover the required query range "
192 f"[{query_offset}, {query_offset + q_len}); mask query "
193 f"length={mask_q_len}"
194 )
195 attention_mask = attention_mask.narrow(
196 -2, query_offset, q_len
197 )
198 call_kwargs["attn_mask"] = attention_mask
199 if call_kwargs.get("is_causal"):
200 call_kwargs["is_causal"] = False
201 return call_kwargs
203 if call_kwargs.get("is_causal"):
204 call_kwargs["is_causal"] = False
205 call_kwargs["attn_mask"] = _cp_offset_causal_mask(
206 q_len, kv_len, query_offset, device
207 )
208 return call_kwargs
211def _prepare_head_tail_sdpa_kwargs(
212 kwargs: dict[str, Any], query: Any, key: Any,
213 cp_mesh: Any) -> tuple[dict[str, Any], dict[str, Any]]:
214 """Prepare complete-mask query rows for both Head-Tail attention calls."""
215 local_q_len = query.shape[2]
216 if local_q_len % 2:
217 raise ValueError(
218 "Head-Tail load balance requires an even local Q sequence "
219 f"length, got {local_q_len}"
220 )
221 half_q_len = local_q_len // 2
222 local_rank = cp_mesh.get_local_rank()
223 peer_rank = cp_mesh.size() - 1 - local_rank
224 global_kv_len = key.shape[2] * cp_mesh.size()
225 keep_kwargs = _prepare_cp_sdpa_kwargs(
226 kwargs,
227 q_len=half_q_len,
228 kv_len=global_kv_len,
229 query_offset=local_rank * local_q_len,
230 device=query.device,
231 )
232 peer_kwargs = _prepare_cp_sdpa_kwargs(
233 kwargs,
234 q_len=half_q_len,
235 kv_len=global_kv_len,
236 query_offset=peer_rank * local_q_len + half_q_len,
237 device=query.device,
238 )
239 return keep_kwargs, peer_kwargs
242def _prepare_hybrid_sdpa_kwargs(
243 kwargs: dict[str, Any], query: Any, key: Any,
244 cp_mesh: Any, ulysses_degree: int) -> dict[str, Any]:
245 """Prepare complete-mask query rows for Hybrid attention."""
246 _, colossal_mesh = _build_hybrid_cp_submeshes(cp_mesh, ulysses_degree)
247 hybrid_q_len = query.shape[2] * ulysses_degree
248 return _prepare_cp_sdpa_kwargs(
249 kwargs,
250 q_len=hybrid_q_len,
251 kv_len=key.shape[2] * cp_mesh.size(),
252 query_offset=colossal_mesh.get_local_rank() * hybrid_q_len,
253 device=query.device,
254 )
257def _cp_sdpa_call(orig_sdpa, cp_mesh, q, k, v, kwargs):
258 """CP-aware SDPA: K/V all-gather + D-04 offset-aware causal mask."""
259 cp_dim = 2 # sequence dim of the [B, N, S, H] layout
260 global_k, global_v = flex_cp_allgather(
261 k.contiguous(), v.contiguous(), cp_dim, cp_mesh)
262 if cp_mesh.size() > 1:
263 kwargs = _prepare_cp_sdpa_kwargs(
264 kwargs,
265 q_len=q.shape[cp_dim],
266 kv_len=global_k.shape[cp_dim],
267 query_offset=cp_mesh.get_local_rank() * q.shape[cp_dim],
268 device=q.device,
269 )
270 return orig_sdpa(q, global_k, global_v, **kwargs)
273def _ulysses_attention_call(
274 attention_fn, cp_mesh, query, key, value, kwargs,
275 *, seq_dim=2, head_dim=1):
276 """Run attention in the Pure Ulysses full-sequence/head-sharded layout."""
277 _validate_ulysses_head_counts(
278 query, key, value, cp_mesh.size(), "Pure Ulysses CP"
279 )
280 query, key, value = (
281 ulysses_seq_to_head(tensor, seq_dim, head_dim, cp_mesh)
282 for tensor in (query, key, value)
283 )
284 output = attention_fn(query, key, value, **kwargs)
285 return ulysses_head_to_seq(output, seq_dim, head_dim, cp_mesh)
288def _ulysses_qkv_forward(original_forward, cp_mesh, args, kwargs):
289 """Preserve a QKV forward signature while applying Pure Ulysses."""
290 signature = inspect.signature(original_forward)
291 bound = signature.bind(*args, **kwargs)
292 names = list(signature.parameters)
293 if len(names) < 3:
294 raise TypeError("Ulysses QKV wrapper requires at least three forward inputs")
295 try:
296 query, key, value = (
297 bound.arguments[names[index]] for index in range(3)
298 )
299 except KeyError as exc:
300 raise TypeError(
301 "Ulysses QKV wrapper requires query, key, and value inputs"
302 ) from exc
303 _validate_ulysses_head_counts(
304 query, key, value, cp_mesh.size(), "Pure Ulysses CP"
305 )
306 query, key, value = (
307 ulysses_seq_to_head(tensor, 2, 1, cp_mesh)
308 for tensor in (query, key, value)
309 )
310 bound.arguments[names[0]] = query
311 bound.arguments[names[1]] = key
312 bound.arguments[names[2]] = value
313 output = original_forward(*bound.args, **bound.kwargs)
314 return ulysses_head_to_seq(output, 2, 1, cp_mesh)
317def _require_ulysses_cp_mesh(cp_mesh, wrapper_name):
318 """Validate the communication context required by Pure Ulysses."""
319 if cp_mesh is None or cp_mesh.size() <= 1:
320 raise ValueError(
321 f"Ulysses wrapper {wrapper_name!r} requires an active CP mesh"
322 )
325# ────────────────────────────────────────────────────────────────────────────
326# The four built-in wrappers
327# ────────────────────────────────────────────────────────────────────────────
329@inner_wrapper
330def sdpa_qkv_cp_wrapper(
331 target_module: Module, mesh: Any, tp_mesh: Any,
332 cp_mesh: Any, ep_mesh: Any) -> Callable:
333 """NeMo/Megatron SDPA path (registry "sdpa_qkv"): explicit all-gather K/V.
335 Assumes the inner_attention.forward(q,k,v,...) signature convention.
336 **Local-only** (injection discipline): the dual-mode adapter converts
337 DTensor inputs to local and re-wraps the output — this wrapper never
338 touches DTensor. Since it wraps an inner submodule, the plan MUST
339 declare ``inner_out_src: "first_input"`` (its output layout == q's
340 layout). cp_mesh is framework-filled context; fail fast when the plan
341 has no cp axis.
342 """
344 del mesh, tp_mesh, ep_mesh
345 if cp_mesh is None:
346 raise ValueError(
347 "The in-repo CP wrapper reference implementation 'sdpa_qkv' requires an "
348 "active cp axis (the communication domain for K/V all-gather), but the "
349 "framework-filled cp_mesh is None (the current plan has no cp axis) — "
350 "without CP, use a custom @inner_wrapper wrapper instead (the "
351 "cp_mesh=None semantics are then your own responsibility), or use the "
352 "local_compute_fn channel (see "
353 "examples/distributed/perf_replacement.py)")
355 original_forward = target_module.forward
357 @functools.wraps(original_forward)
358 def cp_forward(q: Any, k: Any, v: Any, **kwargs: Any) -> Any:
359 """All-gather K/V along CP, then run the original QKV SDPA forward."""
360 return _cp_sdpa_call(original_forward, cp_mesh, q, k, v, kwargs)
362 return cp_forward
365@inner_wrapper
366def flex_qkv_cp_wrapper(
367 target_module: Module, mesh: Any, tp_mesh: Any,
368 cp_mesh: Any, ep_mesh: Any) -> Callable:
369 """NeMo/Megatron FlexAttention path (registry "flex_qkv"): explicit all-gather K/V.
371 **Local-only** (see sdpa_qkv_cp_wrapper); requires
372 ``inner_out_src: "first_input"`` in the plan. Constraint: the
373 block_mask must be built for the global kv length. cp_mesh is
374 framework-filled context; fail fast when the plan has no cp axis.
375 """
377 del mesh, tp_mesh, ep_mesh
378 if cp_mesh is None:
379 raise ValueError(
380 "The in-repo CP wrapper reference implementation 'flex_qkv' requires an "
381 "active cp axis (the communication domain for K/V all-gather), but the "
382 "framework-filled cp_mesh is None (the current plan has no cp axis) — "
383 "without CP, use a custom @inner_wrapper wrapper instead (the "
384 "cp_mesh=None semantics are then your own responsibility), or use the "
385 "local_compute_fn channel (see "
386 "examples/distributed/perf_replacement.py)")
388 original_forward = target_module.forward
390 @functools.wraps(original_forward)
391 def cp_forward(q: Any, k: Any, v: Any, **kwargs: Any) -> Any:
392 """All-gather K/V along CP, then run the original QKV Flex forward."""
393 global_k, global_v = flex_cp_allgather(
394 k.contiguous(), v.contiguous(), 2, cp_mesh)
395 return original_forward(q, global_k, global_v, **kwargs)
397 return cp_forward
400@inner_wrapper
401def sdpa_hf_cp_wrapper(
402 target_module: Module, mesh: Any, tp_mesh: Any,
403 cp_mesh: Any, ep_mesh: Any) -> Callable:
404 """HF standard SDPA path: forward(hidden_states,...) -> primitive interception (05 §4.4.2).
406 **Local-only** (see sdpa_qkv_cp_wrapper): the adapter handles DTensor
407 unwrap/param-unwrap/rewrap; the rewrap uses the boundary's declared
408 out_src (this wrapper targets the boundary module itself). The
409 primitive interception is a temporary global function replacement
410 (restored via try/finally) and is not thread-safe; it is safe under
411 single-process SPMD training (consistent with the TorchTitan CP
412 implementation).
413 Misfire detection: the wrapper may be applied to a module that does not
414 call F.sdpa -- if the primitive did not intercept a single call, the K/V
415 were not gathered (a silent numerical error), so raise a RuntimeError
416 immediately.
417 """
419 del mesh, tp_mesh, ep_mesh
420 if cp_mesh is None:
421 raise ValueError(
422 "The in-repo CP wrapper reference implementation 'sdpa_hf' requires an "
423 "active cp axis (the communication domain for K/V all-gather), but the "
424 "framework-filled cp_mesh is None (the current plan has no cp axis) — "
425 "without CP, use a custom @inner_wrapper wrapper instead (the "
426 "cp_mesh=None semantics are then your own responsibility), or use the "
427 "local_compute_fn channel (see "
428 "examples/distributed/perf_replacement.py)")
430 setattr(target_module, "_hp_sdpa_hf_cp_mesh", cp_mesh)
431 setattr(target_module, "_hp_sdpa_hf_original_forward", target_module.forward)
433 @functools.wraps(target_module.forward)
434 def cp_forward(hidden_states: Any, *args: Any, **kwargs: Any) -> Any:
435 """Delegate to the source-visible SDPA helper shared with Codegen."""
436 return sdpa_hf_cp_forward(target_module, hidden_states, *args, **kwargs)
438 return cp_forward
441def sdpa_hf_cp_forward(
442 target_module: Module, hidden_states: Any,
443 *args: Any, **kwargs: Any) -> Any:
444 """Run an HF attention forward while intercepting SDPA for CP."""
445 cp_mesh = getattr(target_module, "_hp_sdpa_hf_cp_mesh")
446 original_forward = getattr(target_module, "_forward_impl", None)
447 if original_forward is None:
448 original_forward = getattr(target_module, "_hp_sdpa_hf_original_forward")
449 orig_sdpa = F.scaled_dot_product_attention
450 fired = {"hit": False}
452 def cp_aware_sdpa(q: Any, k: Any, v: Any, **kw: Any) -> Any:
453 """CP-aware SDPA replacement: all-gather K/V plus the D-04 mask."""
454 fired["hit"] = True
455 return _cp_sdpa_call(orig_sdpa, cp_mesh, q, k, v, kw)
457 F.scaled_dot_product_attention = cp_aware_sdpa
458 try:
459 out = original_forward(hidden_states, *args, **kwargs)
460 finally:
461 F.scaled_dot_product_attention = orig_sdpa
462 if not fired["hit"]:
463 raise RuntimeError(
464 f"CP wrapper 'sdpa_hf' did not intercept any "
465 f"F.scaled_dot_product_attention call on "
466 f"{type(target_module).__name__} -- the wrapper does "
467 f"not match the module implementation (K/V were not "
468 f"all-gathered; continuing would produce silent numerical "
469 f"errors). Please explicitly set inner_wrapper='sdpa_qkv' "
470 f"(the (q,k,v) convention), or provide a custom inner_wrapper "
471 f"callable")
472 return out
475@inner_wrapper
476def flex_hf_cp_wrapper(
477 target_module: Module, mesh: Any, tp_mesh: Any,
478 cp_mesh: Any, ep_mesh: Any) -> Callable:
479 """HF standard FlexAttention path: intercept flex_attention (same structure as the SDPA path).
481 **Local-only** (see sdpa_qkv_cp_wrapper). Constraint:
482 score_mod/block_mask pass through verbatim via kwargs -- under CP,
483 kv_len changes from S/cp to S, so the block_mask must be built for the
484 **global kv length** (constructed on the full sequence in the data
485 pipeline / model side), otherwise shapes and semantics are misaligned.
486 The wrapper does not validate this.
487 Misfire detection is the same as 'sdpa_hf': if no flex_attention call is
488 intercepted, raise a RuntimeError.
489 """
491 del mesh, tp_mesh, ep_mesh
492 if cp_mesh is None:
493 raise ValueError(
494 "The in-repo CP wrapper reference implementation 'flex_hf' requires an "
495 "active cp axis (the communication domain for K/V all-gather), but the "
496 "framework-filled cp_mesh is None (the current plan has no cp axis) — "
497 "without CP, use a custom @inner_wrapper wrapper instead (the "
498 "cp_mesh=None semantics are then your own responsibility), or use the "
499 "local_compute_fn channel (see "
500 "examples/distributed/perf_replacement.py)")
502 original_forward = target_module.forward
503 # FlexAttention is optional on older supported PyTorch versions.
504 flex_attention_module = importlib.import_module(
505 "torch.nn.attention.flex_attention")
506 original_flex_attention = flex_attention_module.flex_attention
508 @functools.wraps(original_forward)
509 def cp_forward(hidden_states: Any, *args: Any, **kwargs: Any) -> Any:
510 """Run the HF forward with flex_attention temporarily replaced."""
511 fired = {"hit": False}
513 def cp_aware_flex(q: Any, k: Any, v: Any, **kw: Any) -> Any:
514 """CP-aware FlexAttention replacement: all-gather K/V first."""
515 fired["hit"] = True
516 global_k, global_v = flex_cp_allgather(
517 k.contiguous(), v.contiguous(), 2, cp_mesh)
518 return original_flex_attention(q, global_k, global_v, **kw)
520 flex_attention_module.flex_attention = cp_aware_flex
521 try:
522 out = original_forward(hidden_states, *args, **kwargs)
523 finally:
524 flex_attention_module.flex_attention = original_flex_attention
525 if not fired["hit"]:
526 raise RuntimeError(
527 f"CP wrapper 'flex_hf' did not intercept any flex_attention "
528 f"call on {type(target_module).__name__} -- the wrapper "
529 f"does not match the module implementation (K/V were "
530 f"not all-gathered; continuing would produce silent numerical "
531 f"errors). Please explicitly set inner_wrapper='flex_qkv' "
532 f"(the (q,k,v) convention), or provide a custom inner_wrapper "
533 f"callable")
534 return out
536 return cp_forward
539# ────────────────────────────────────────────────────────────────────────────
540# Colossal Head-Tail load-balance wrappers (explicit plan_overrides methods)
541# ────────────────────────────────────────────────────────────────────────────
543@inner_wrapper
544def sdpa_qkv_load_balance_cp_wrapper(
545 target_module: Module, mesh: Any, tp_mesh: Any,
546 cp_mesh: Any, ep_mesh: Any) -> Callable:
547 """Apply Colossal Head-Tail load balancing to a QKV-style SDPA module.
549 Args:
550 target_module: Attention module whose first three inputs are Q/K/V.
551 mesh: Framework-owned root mesh; unused by this wrapper.
552 tp_mesh: Framework-owned TP mesh; unused by this wrapper.
553 cp_mesh: Framework-owned CP communication mesh.
554 ep_mesh: Framework-owned EP mesh; unused by this wrapper.
555 """
556 del mesh, tp_mesh, ep_mesh
557 if cp_mesh is None or cp_mesh.size() <= 1:
558 raise ValueError(
559 "sdpa_qkv_load_balance_cp_wrapper requires an active CP mesh"
560 )
561 original_forward = target_module.forward
563 @functools.wraps(original_forward)
564 def cp_forward(q: Any, k: Any, v: Any, **kwargs: Any) -> Any:
565 """Route local Q/K/V tensors through Head-Tail communication."""
566 def attention_call(
567 query: Any, key: Any, value: Any,
568 call_kwargs: dict[str, Any]) -> Any:
569 """Invoke the original QKV forward with transformed tensors."""
570 return original_forward(query, key, value, **call_kwargs)
572 keep_kwargs, peer_kwargs = _prepare_head_tail_sdpa_kwargs(
573 kwargs, q, k, cp_mesh
574 )
575 return head_tail_load_balance_attention(
576 attention_call,
577 q,
578 k,
579 v,
580 keep_kwargs,
581 cp_mesh,
582 peer_attention_kwargs=peer_kwargs,
583 )
585 return cp_forward
588@inner_wrapper
589def sdpa_hf_load_balance_cp_wrapper(
590 target_module: Module, mesh: Any, tp_mesh: Any,
591 cp_mesh: Any, ep_mesh: Any) -> Callable:
592 """Apply Colossal Head-Tail load balancing at an HF SDPA primitive.
594 Args:
595 target_module: HF-style attention containing an SDPA primitive call.
596 mesh: Framework-owned root mesh; unused by this wrapper.
597 tp_mesh: Framework-owned TP mesh; unused by this wrapper.
598 cp_mesh: Framework-owned CP communication mesh.
599 ep_mesh: Framework-owned EP mesh; unused by this wrapper.
600 """
601 del mesh, tp_mesh, ep_mesh
602 if cp_mesh is None or cp_mesh.size() <= 1:
603 raise ValueError(
604 "sdpa_hf_load_balance_cp_wrapper requires an active CP mesh"
605 )
606 original_forward = target_module.forward
607 original_sdpa = F.scaled_dot_product_attention
609 @functools.wraps(original_forward)
610 def cp_forward(
611 hidden_states: Any, *args: Any, **kwargs: Any) -> Any:
612 """Intercept the module's SDPA primitive for one forward call."""
613 fired = {"hit": False}
615 def load_balanced_sdpa(
616 q: Any, k: Any, v: Any,
617 **call_kwargs: Any) -> Any:
618 """Run one intercepted SDPA call with Head-Tail communication."""
619 fired["hit"] = True
620 keep_kwargs, peer_kwargs = _prepare_head_tail_sdpa_kwargs(
621 call_kwargs, q, k, cp_mesh
622 )
624 def _call_original_sdpa(query, key, value, attention_kwargs):
625 return original_sdpa(query, key, value, **attention_kwargs)
627 return head_tail_load_balance_attention(
628 _call_original_sdpa,
629 q,
630 k,
631 v,
632 keep_kwargs,
633 cp_mesh,
634 peer_attention_kwargs=peer_kwargs,
635 )
637 F.scaled_dot_product_attention = load_balanced_sdpa
638 try:
639 output = original_forward(hidden_states, *args, **kwargs)
640 finally:
641 F.scaled_dot_product_attention = original_sdpa
642 if not fired["hit"]:
643 raise RuntimeError(
644 "CP wrapper 'sdpa_hf_load_balance' did not intercept any "
645 "F.scaled_dot_product_attention call on "
646 f"{type(target_module).__name__}; choose the QKV wrapper or "
647 "provide a matching custom inner_wrapper"
648 )
649 return output
651 return cp_forward
654# ────────────────────────────────────────────────────────────────────────────
655# Pure Ulysses attention wrappers (explicit plan_overrides methods)
656# ────────────────────────────────────────────────────────────────────────────
658@inner_wrapper
659def sdpa_qkv_ulysses_cp_wrapper(
660 target_module: Module, mesh: Any, tp_mesh: Any,
661 cp_mesh: Any, ep_mesh: Any) -> Callable:
662 """Apply Pure Ulysses to a separated ``forward(query, key, value, ...)``."""
663 del mesh, tp_mesh, ep_mesh
664 _require_ulysses_cp_mesh(cp_mesh, "sdpa_qkv_ulysses")
665 original_forward = target_module.forward
667 @functools.wraps(original_forward)
668 def cp_forward(*args: Any, **kwargs: Any) -> Any:
669 """Run the original QKV forward in the Ulysses head-sharded layout."""
670 return _ulysses_qkv_forward(original_forward, cp_mesh, args, kwargs)
672 return cp_forward
675@inner_wrapper
676def flex_qkv_ulysses_cp_wrapper(
677 target_module: Module, mesh: Any, tp_mesh: Any,
678 cp_mesh: Any, ep_mesh: Any) -> Callable:
679 """Apply Pure Ulysses to a separated FlexAttention QKV forward."""
680 del mesh, tp_mesh, ep_mesh
681 _require_ulysses_cp_mesh(cp_mesh, "flex_qkv_ulysses")
682 original_forward = target_module.forward
684 @functools.wraps(original_forward)
685 def cp_forward(*args: Any, **kwargs: Any) -> Any:
686 """Run the original FlexAttention QKV forward in the Ulysses layout."""
687 return _ulysses_qkv_forward(original_forward, cp_mesh, args, kwargs)
689 return cp_forward
692@inner_wrapper
693def sdpa_hf_ulysses_cp_wrapper(
694 target_module: Module, mesh: Any, tp_mesh: Any,
695 cp_mesh: Any, ep_mesh: Any) -> Callable:
696 """Apply Pure Ulysses by intercepting HF SDPA primitive calls."""
697 del mesh, tp_mesh, ep_mesh
698 _require_ulysses_cp_mesh(cp_mesh, "sdpa_hf_ulysses")
699 original_forward = target_module.forward
700 original_sdpa = F.scaled_dot_product_attention
702 @functools.wraps(original_forward)
703 def cp_forward(*args: Any, **kwargs: Any) -> Any:
704 """Run the HF forward with F.sdpa temporarily Ulysses-exchanged."""
705 fired = {"hit": False}
707 def ulysses_sdpa(
708 query: Any, key: Any, value: Any,
709 **attention_kwargs: Any) -> Any:
710 """Run one intercepted SDPA call in the Ulysses layout."""
711 fired["hit"] = True
712 return _ulysses_attention_call(
713 original_sdpa,
714 cp_mesh,
715 query,
716 key,
717 value,
718 attention_kwargs,
719 )
721 F.scaled_dot_product_attention = ulysses_sdpa
722 try:
723 output = original_forward(*args, **kwargs)
724 finally:
725 F.scaled_dot_product_attention = original_sdpa
726 if not fired["hit"]:
727 raise RuntimeError(
728 "CP wrapper 'sdpa_hf_ulysses' did not intercept any "
729 "F.scaled_dot_product_attention call; the selected wrapper "
730 "does not match the module implementation"
731 )
732 return output
734 return cp_forward
737@inner_wrapper
738def flex_hf_ulysses_cp_wrapper(
739 target_module: Module, mesh: Any, tp_mesh: Any,
740 cp_mesh: Any, ep_mesh: Any) -> Callable:
741 """Apply Pure Ulysses by intercepting HF FlexAttention primitive calls."""
742 del mesh, tp_mesh, ep_mesh
743 _require_ulysses_cp_mesh(cp_mesh, "flex_hf_ulysses")
744 original_forward = target_module.forward
745 flex_attention_module = importlib.import_module(
746 "torch.nn.attention.flex_attention"
747 )
748 original_flex_attention = flex_attention_module.flex_attention
750 @functools.wraps(original_forward)
751 def cp_forward(*args: Any, **kwargs: Any) -> Any:
752 """Run the HF forward with flex_attention temporarily Ulysses-exchanged."""
753 fired = {"hit": False}
755 def ulysses_flex(
756 query: Any, key: Any, value: Any,
757 **attention_kwargs: Any) -> Any:
758 """Run one intercepted FlexAttention call in the Ulysses layout."""
759 fired["hit"] = True
760 return _ulysses_attention_call(
761 original_flex_attention,
762 cp_mesh,
763 query,
764 key,
765 value,
766 attention_kwargs,
767 )
769 flex_attention_module.flex_attention = ulysses_flex
770 try:
771 output = original_forward(*args, **kwargs)
772 finally:
773 flex_attention_module.flex_attention = original_flex_attention
774 if not fired["hit"]:
775 raise RuntimeError(
776 "CP wrapper 'flex_hf_ulysses' did not intercept any "
777 "flex_attention call; the selected wrapper does not match "
778 "the module implementation"
779 )
780 return output
782 return cp_forward
785# ────────────────────────────────────────────────────────────────────────────
786# Hybrid attention wrappers (explicit Target with wrapper-local degree)
787# ────────────────────────────────────────────────────────────────────────────
789def _validate_hybrid_config(
790 cp_mesh: Any, ulysses_degree: int, wrapper_name: str) -> None:
791 """Validate Hybrid topology at wrapper installation time."""
792 if cp_mesh is None or cp_mesh.size() <= 1:
793 raise ValueError(
794 f"Hybrid wrapper {wrapper_name!r} requires an active CP mesh"
795 )
796 if isinstance(ulysses_degree, bool) or not isinstance(ulysses_degree, int):
797 raise TypeError(
798 f"Hybrid wrapper {wrapper_name!r} requires integer "
799 f"ulysses_degree, got {type(ulysses_degree).__name__}"
800 )
801 cp_size = cp_mesh.size()
802 if not 1 < ulysses_degree < cp_size:
803 raise ValueError(
804 f"Hybrid wrapper {wrapper_name!r} requires 1 < ulysses_degree "
805 f"< cp_size, got ulysses_degree={ulysses_degree}, cp_size={cp_size}"
806 )
807 if cp_size % ulysses_degree:
808 raise ValueError(
809 f"cp_size ({cp_size}) must be divisible by ulysses_degree "
810 f"({ulysses_degree})"
811 )
814def _apply_qkv_hybrid_wrapper(
815 target_module, cp_mesh, ulysses_degree, wrapper_name, *,
816 prepare_sdpa_mask: bool):
817 """Replace a separated QKV forward with local-tensor Hybrid CP."""
818 _validate_hybrid_config(cp_mesh, ulysses_degree, wrapper_name)
819 original_forward = target_module.forward
821 @functools.wraps(original_forward)
822 def cp_forward(q: Any, k: Any, v: Any, **kwargs: Any) -> Any:
823 """Run the original QKV forward through local-tensor Hybrid CP."""
824 def attention_call(
825 query: Any, key: Any, value: Any,
826 call_kwargs: dict[str, Any]) -> Any:
827 """Invoke the original QKV forward with transformed tensors."""
828 return original_forward(query, key, value, **call_kwargs)
830 if prepare_sdpa_mask:
831 kwargs = _prepare_hybrid_sdpa_kwargs(
832 kwargs, q, k, cp_mesh, ulysses_degree
833 )
834 return hybrid_cp_attention(
835 attention_call,
836 q,
837 k,
838 v,
839 kwargs,
840 cp_mesh,
841 ulysses_degree,
842 )
844 return cp_forward
847@inner_wrapper
848def sdpa_qkv_hybrid_cp_wrapper(
849 target_module: Module, mesh: Any, tp_mesh: Any, cp_mesh: Any,
850 ep_mesh: Any, ulysses_degree: int) -> Callable:
851 """Apply Hybrid CP to a separated SDPA ``forward(query, key, value, ...)``."""
852 del mesh, tp_mesh, ep_mesh
853 return _apply_qkv_hybrid_wrapper(
854 target_module,
855 cp_mesh,
856 ulysses_degree,
857 "sdpa_qkv_hybrid",
858 prepare_sdpa_mask=True,
859 )
862@inner_wrapper
863def flex_qkv_hybrid_cp_wrapper(
864 target_module: Module, mesh: Any, tp_mesh: Any, cp_mesh: Any,
865 ep_mesh: Any, ulysses_degree: int) -> Callable:
866 """Apply Hybrid CP to a separated FlexAttention QKV forward."""
867 del mesh, tp_mesh, ep_mesh
868 return _apply_qkv_hybrid_wrapper(
869 target_module,
870 cp_mesh,
871 ulysses_degree,
872 "flex_qkv_hybrid",
873 prepare_sdpa_mask=False,
874 )
877@inner_wrapper
878def sdpa_hf_hybrid_cp_wrapper(
879 target_module: Module, mesh: Any, tp_mesh: Any, cp_mesh: Any,
880 ep_mesh: Any, ulysses_degree: int) -> Callable:
881 """Apply Hybrid CP by intercepting HF SDPA primitive calls."""
882 del mesh, tp_mesh, ep_mesh
883 _validate_hybrid_config(cp_mesh, ulysses_degree, "sdpa_hf_hybrid")
884 original_forward = target_module.forward
885 original_sdpa = F.scaled_dot_product_attention
887 @functools.wraps(original_forward)
888 def cp_forward(*args: Any, **kwargs: Any) -> Any:
889 """Run the HF attention forward with temporary Hybrid SDPA interception."""
890 fired = {"hit": False}
892 def hybrid_sdpa(
893 query: Any, key: Any, value: Any,
894 **attention_kwargs: Any) -> Any:
895 """Route one intercepted SDPA call through Hybrid CP."""
896 fired["hit"] = True
897 attention_kwargs = _prepare_hybrid_sdpa_kwargs(
898 attention_kwargs,
899 query,
900 key,
901 cp_mesh,
902 ulysses_degree,
903 )
905 def _call_original_sdpa(call_query, call_key, call_value, call_kwargs):
906 return original_sdpa(
907 call_query, call_key, call_value, **call_kwargs
908 )
910 return hybrid_cp_attention(
911 _call_original_sdpa,
912 query,
913 key,
914 value,
915 attention_kwargs,
916 cp_mesh,
917 ulysses_degree,
918 )
920 F.scaled_dot_product_attention = hybrid_sdpa
921 try:
922 output = original_forward(*args, **kwargs)
923 finally:
924 F.scaled_dot_product_attention = original_sdpa
925 if not fired["hit"]:
926 raise RuntimeError(
927 "CP wrapper 'sdpa_hf_hybrid' did not intercept any "
928 "F.scaled_dot_product_attention call; the selected wrapper "
929 "does not match the module implementation"
930 )
931 return output
933 return cp_forward
936@inner_wrapper
937def flex_hf_hybrid_cp_wrapper(
938 target_module: Module, mesh: Any, tp_mesh: Any, cp_mesh: Any,
939 ep_mesh: Any, ulysses_degree: int) -> Callable:
940 """Apply Hybrid CP by intercepting HF FlexAttention primitive calls."""
941 del mesh, tp_mesh, ep_mesh
942 _validate_hybrid_config(cp_mesh, ulysses_degree, "flex_hf_hybrid")
943 original_forward = target_module.forward
944 flex_attention_module = importlib.import_module(
945 "torch.nn.attention.flex_attention"
946 )
947 original_flex_attention = flex_attention_module.flex_attention
949 @functools.wraps(original_forward)
950 def cp_forward(*args: Any, **kwargs: Any) -> Any:
951 """Run the HF attention forward with temporary Hybrid Flex interception."""
952 fired = {"hit": False}
954 def hybrid_flex(
955 query: Any, key: Any, value: Any,
956 **attention_kwargs: Any) -> Any:
957 """Route one intercepted FlexAttention call through Hybrid CP."""
958 fired["hit"] = True
960 def _call_original_flex(call_query, call_key, call_value, call_kwargs):
961 return original_flex_attention(
962 call_query, call_key, call_value, **call_kwargs
963 )
965 return hybrid_cp_attention(
966 _call_original_flex,
967 query,
968 key,
969 value,
970 attention_kwargs,
971 cp_mesh,
972 ulysses_degree,
973 )
975 flex_attention_module.flex_attention = hybrid_flex
976 try:
977 output = original_forward(*args, **kwargs)
978 finally:
979 flex_attention_module.flex_attention = original_flex_attention
980 if not fired["hit"]:
981 raise RuntimeError(
982 "CP wrapper 'flex_hf_hybrid' did not intercept any "
983 "flex_attention call; the selected wrapper does not match "
984 "the module implementation"
985 )
986 return output
988 return cp_forward
991# ────────────────────────────────────────────────────────────────────────────
992# MLA/DSA Ulysses wrapper
993# ────────────────────────────────────────────────────────────────────────────
995def _input_cp_sharding(text_model, context):
996 """Build the CP-rank input-slicing rewrite request for a text model."""
997 if getattr(text_model, _ULYSSES_WRAPPED_FLAG, False):
998 return None
999 original_forward = text_model.forward
1001 @functools.wraps(original_forward)
1002 def forward_with_sequence_sharding(*args: Any, **kwargs: Any) -> Any:
1003 """Slice sequence-dim inputs to this CP rank before the forward."""
1004 if getattr(text_model, "_hyper_cp_inside_forward", False):
1005 return original_forward(*args, **kwargs)
1006 call_kwargs = kwargs.copy()
1007 inputs_embeds = call_kwargs.get("inputs_embeds")
1008 if inputs_embeds is None:
1009 return original_forward(*args, **kwargs)
1010 call_kwargs["inputs_embeds"] = _slice_sequence(inputs_embeds, 1, context)
1011 position_ids = call_kwargs.get("position_ids")
1012 if position_ids is not None:
1013 call_kwargs["position_ids"] = _slice_sequence(
1014 position_ids, position_ids.ndim - 1, context)
1015 mome_mask = call_kwargs.get("mome_mask")
1016 if mome_mask is not None:
1017 call_kwargs["mome_mask"] = _slice_sequence(mome_mask, 1, context)
1018 if call_kwargs.get("use_cache"):
1019 raise ValueError("Ulysses CP requires use_cache=False")
1020 call_kwargs["use_cache"] = False
1021 setattr(text_model, "_hyper_cp_inside_forward", True)
1022 try:
1023 return original_forward(*args, **call_kwargs)
1024 finally:
1025 setattr(text_model, "_hyper_cp_inside_forward", False)
1027 return _ForwardRewriteRequest(
1028 text_model,
1029 forward_with_sequence_sharding,
1030 companion_attrs={_ULYSSES_WRAPPED_FLAG: True},
1031 )
1034def _validate_ulysses_requirements(target_module, cp_size):
1035 """Validate the model configuration supported by Ulysses CP."""
1036 config = getattr(target_module, "config", None)
1037 if config is None:
1038 raise ValueError(
1039 "MLA/DSA Ulysses wrapper requires target_module.config")
1040 text_config = getattr(config, "text_config", config)
1041 if text_config is None:
1042 raise ValueError(
1043 "MLA/DSA Ulysses wrapper requires a non-None text_config")
1044 for name in ("num_attention_heads", "index_num_attention_heads"):
1045 value = getattr(text_config, name, None)
1046 if value is None:
1047 raise ValueError(
1048 "MLA/DSA Ulysses wrapper requires "
1049 f"text_config.{name}")
1050 count = int(value)
1051 if count % cp_size:
1052 raise ValueError(
1053 f"{name}={count} is not divisible by CP size {cp_size}")
1054 if getattr(text_config, "dsa_dense_warm_up", False):
1055 raise ValueError("MLA/DSA CP does not support DSA dense warm-up")
1056 if not getattr(text_config, "apply_fa_rescale", False):
1057 raise ValueError("MLA/DSA CP requires apply_fa_rescale=True")
1058 if getattr(text_config, "use_fused_sink_fa", False):
1059 raise ValueError("MLA/DSA CP does not support fused sink FA")
1062def _collect_mla_dsa_text_models(target_module):
1063 """Collect text-model modules supported by the MLA/DSA wrapper.
1065 Args:
1066 target_module: Root module whose descendants are inspected.
1068 Returns:
1069 The matching text-model modules in traversal order.
1070 """
1071 text_models = []
1072 for name, module in target_module.named_modules():
1073 if name.rsplit(".", maxsplit=1)[-1] in {"text_model", "language_model"}:
1074 text_models.append(module)
1075 return text_models
1078def _collect_mla_dsa_attention_registries(attention_module):
1079 """Collect registries that expose both required MLA/DSA backends.
1081 Args:
1082 attention_module: Python module that owns the attention registries.
1084 Returns:
1085 Dictionaries containing both required attention functions.
1086 """
1087 attention_registries = []
1088 required_attention_functions = {"npu_fa_rescale", "dsa_sparse_attention"}
1089 for value in vars(attention_module).values():
1090 if isinstance(value, dict) and required_attention_functions <= value.keys():
1091 attention_registries.append(value)
1092 return attention_registries
1095@inner_wrapper
1096def mla_dsa_ulysses_cp_wrapper( # pylint: disable=inconsistent-return-statements
1097 target_module: Module, mesh: Any, tp_mesh: Any,
1098 cp_mesh: Any, ep_mesh: Any) -> Any:
1099 """Configure input, MoME, MLA and DSA Ulysses adaptations."""
1100 del mesh, tp_mesh, ep_mesh
1101 if cp_mesh is None or cp_mesh.size() <= 1:
1102 raise ValueError(
1103 "MLA/DSA Ulysses wrapper requires an active CP mesh")
1104 if getattr(target_module, _ULYSSES_WRAPPED_FLAG, False):
1105 return
1106 _validate_ulysses_requirements(target_module, cp_mesh.size())
1107 context = _UlyssesContext(cp_mesh)
1109 text_models = _collect_mla_dsa_text_models(target_module)
1110 if not text_models:
1111 raise RuntimeError("Cannot find a text or language model")
1112 requests = []
1113 for text_model in text_models:
1114 request = _input_cp_sharding(text_model, context)
1115 if request is not None:
1116 requests.append(request)
1118 attention_modules = {
1119 inspect.getmodule(module) for module in target_module.modules()
1120 if getattr(module, "attention_type", None) in {"mla", "dsa"}}
1121 attention_modules.discard(None)
1122 if len(attention_modules) != 1:
1123 names = sorted(module.__name__ for module in attention_modules)
1124 raise RuntimeError(
1125 f"Expected one MLA/DSA attention module, found {names}")
1126 attention_module = next(iter(attention_modules))
1127 attention_registries = _collect_mla_dsa_attention_registries(attention_module)
1128 if len(attention_registries) != 1:
1129 raise RuntimeError(
1130 "Expected one attention-function registry containing MLA and DSA backends")
1131 attention_functions = attention_registries[0]
1132 _mome_cp_halo_exchange(attention_module, context)
1133 _mla_cp_alltoall(attention_functions, context)
1134 _dsa_cp_alltoall(attention_module, attention_functions, context)
1136 original_forward = target_module.forward
1138 @functools.wraps(original_forward)
1139 def forward_with_ulysses_adapters(*args: Any, **kwargs: Any) -> Any:
1140 """Pass the forward through; the adapters are installed out of band."""
1141 return original_forward(*args, **kwargs)
1143 requests.append(_ForwardRewriteRequest(
1144 target_module,
1145 forward_with_ulysses_adapters,
1146 companion_attrs={
1147 "_hyper_ulysses_context": context,
1148 _ULYSSES_WRAPPED_FLAG: True,
1149 },
1150 ))
1151 return requests
1154@inner_wrapper
1155def gdn_ulysses_cp_wrapper(
1156 target_module: Any,
1157 mesh: Any,
1158 tp_mesh: Any,
1159 cp_mesh: Any,
1160 ep_mesh: Any,
1161) -> None:
1162 """Install primitive-level Ulysses CP while preserving the model forward."""
1163 del mesh, tp_mesh, ep_mesh
1164 install_gdn_ulysses_cp(target_module, cp_mesh)
1167# {registry_name: wrapper_fn} -- inner-wrapper named registry (05 §4.4.2).
1168# The mechanism is not CP-gated (declaration means application); the in-repo
1169# reference implementations carry CP semantics (their self-checks require an
1170# active cp axis); users may register arbitrary named schemes.
1171# Contract: @inner_wrapper fn(target_module, mesh, tp_mesh, cp_mesh,
1172# ep_mesh) RETURNS the replacement forward (K/V all-gather + dual-mode
1173# tolerance); the forward rewriter installs it (external wrappers may
1174# still replace in place and return None). Users may register their own
1175# named schemes:
1176# INNER_WRAPPER_REGISTRY["my_flash"] = my_fn, after which
1177# spec.inner_wrapper="my_flash" references it by name.
1178INNER_WRAPPER_REGISTRY = {
1179 "sdpa_qkv": sdpa_qkv_cp_wrapper, # NeMo convention forward(q,k,v,...) + D-04 mask
1180 "sdpa_hf": sdpa_hf_cp_wrapper, # HF convention + F.sdpa primitive interception (misfire detection)
1181 "flex_qkv": flex_qkv_cp_wrapper,
1182 "flex_hf": flex_hf_cp_wrapper,
1183 "sdpa_qkv_ulysses": sdpa_qkv_ulysses_cp_wrapper,
1184 "flex_qkv_ulysses": flex_qkv_ulysses_cp_wrapper,
1185 "sdpa_hf_ulysses": sdpa_hf_ulysses_cp_wrapper,
1186 "flex_hf_ulysses": flex_hf_ulysses_cp_wrapper,
1187 "mla_dsa_ulysses": mla_dsa_ulysses_cp_wrapper,
1188 "gdn_ulysses": gdn_ulysses_cp_wrapper,
1189}
1191# Static requirements for shipped wrappers. Custom registry entries own their
1192# semantics; built-ins are known to contain CP collectives and therefore must
1193# run as black-box local regions during placement validation.
1194INNER_WRAPPER_REQUIREMENTS = {
1195 name: {
1196 "requires_cp": True,
1197 "region_dispatch": False,
1198 "forward_style": (
1199 "hf_hidden_states"
1200 if name.endswith("_hf") or "_hf_" in name
1201 else "qkv"
1202 ),
1203 }
1204 for name in INNER_WRAPPER_REGISTRY
1205}