Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/transformers/modeling_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,11 @@ class PreTrainedModel(
# Model's compatible flash kernels (e.g., "kernels-community/flash-mla") defaulting to the first in the list
_compatible_flash_implementations: list[str] | None = None

# Set to `False` by models that can never run under context parallelism, whatever their config
# (attention sinks, for instance, which SDPA cannot express). Models whose *config* rules it out are
# handled by `supports_context_parallel` below, so this stays `True` for almost everything.
_supports_context_parallel: bool = True

# Advanced functionalities support
supports_gradient_checkpointing: bool = False
_can_compile_fullgraph: bool = False
Expand All @@ -1250,6 +1255,25 @@ class PreTrainedModel(
# A mapping describing what outputs can be captured by `capture_outputs` decorator during the forward pass
_can_record_outputs: dict | None = None

@property
def supports_context_parallel(self) -> bool:
"""Whether this model can be trained with context parallelism.

Context parallelism shards the sequence and can only express full causal attention: the per-layer
mask is dropped, so a layer using a stricter mask (sliding-window or chunked attention) would
silently train as full causal instead. A layer carrying a recurrent state along the sequence
(linear attention) is ruled out for a different reason: the state is never exchanged between ranks.
"""
if not self._supports_context_parallel:
return False
config = self.config.get_text_config()
layer_types = getattr(config, "layer_types", None)
if layer_types is not None:
return all(layer_type == "full_attention" for layer_type in layer_types)
# Models predating `layer_types` (Mistral, for one) apply a sliding window to every layer whenever
# `sliding_window` is set.
return getattr(config, "sliding_window", None) is None

@property
@torch.compiler.allow_in_graph
def can_record_outputs(self) -> dict[str, OutputRecorder]:
Expand Down
Loading