Refuse context parallelism for models with sliding-window or chunked attention layers - #4177
Conversation
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
…te is never exchanged
|
Extends the guard to the Ulysses path, which had none. |
SunMarc
left a comment
There was a problem hiding this comment.
Thanks ! I don't mind having them here but if possible, it is better to have these in transformers.
_attach_context_parallel_hooksattaches this hook to everyself_attnmodule:Its own docstring says it will "check if it is a causal mask, if yes, will add a kwarg
is_causal=True, otherwise will raise an error". The implementation does neither check nor raise: it discards whatever mask the layer was given.Replacing the mask with
is_causal=Trueis only equivalent for a plain causal mask. For a model whose layersuse a stricter mask (sliding-window or chunked attention) the layer is silently switched to full
causal attention.
That is most of the current crop, not a legacy corner: gpt-oss makes every other layer sliding (window 128), Gemma 4 makes 5 of every 6 (window 512), Gemma 3 the same ratio (window 1024), Muse-Glimmer-30B 39 of its 52 layers (window 2048), and Mistral/Ministral every layer.
Training runs, loss looks plausible, and the model is trained with the wrong attention pattern. There is one unanswered user report of exactly this (PyTorch forums: "training speed improved significantly — but model performance dropped").
Note this hook is what creates the silence: with the hook removed, torch itself raises a shape error for these models (
The expanded size of the tensor (512) must match the existing size (256) …). So the behavior being replaced is not "working", it is a wrong-but-quiet run where torch would have refused.Repro
Weight-independent probe: perturb one token at position 0 and count how many output positions change. Under a correctly applied window
W, only positions within reach may change (two layers reach2W); under full causal, every later position changes.On
main:With this PR the same command stops instead:
The same probe with two packed documents (block-diagonal mask via restarting
position_ids) gives 50.0% without CP and 100.0% with CP: packed documents attend across their boundaries.repro_cp_mask_drop.pyThe fix
Reject these models when the hooks are attached, before any training happens:
layer_typesalone is not enough: only 80 of the 491 model configs in Transformers define it, and Mistral deliberately does not (it warns and points you at Ministral instead) while still building a sliding-window mask for every layer wheneverconfig.sliding_windowis set. Checkinglayer_typesfirst and falling back tosliding_windowkeeps the models that merely carry a stalesliding_windowvalue (Qwen3 sets it whilelayer_typesis allfull_attention) from being rejected.and correct the docstring to describe what the hook actually does.
Verified
layer_typeshassliding_attention)layer_types(Mistral-7B-v0.1)Checked against real configs:
Qwen3-8B,Qwen3-32B,Qwen3-0.6B,Qwen3-30B-A3B-Baseand the VLMQwen3-VL-2B-Instruct,Mixtral-8x7B-v0.1andMistral-7B-v0.3(which turned its sliding window off) are allowed;google/gemma-2-2b,google/gemma-3-4b-it,Ministral-8B-Instruct-2410andMistral-7B-v0.1raise. Edge cases are inert rather than fatal: a module with noconfigat all, or a config withoutlayer_types, passes through untouched.