fix(post_train): Fix Tunix is_update_step signature and Qwix LoRA FSDP mesh sharding - #4866
fix(post_train): Fix Tunix is_update_step signature and Qwix LoRA FSDP mesh sharding#4866RexBearIU wants to merge 7 commits into
Conversation
…ng in MaxText - Update MaxTextPeftTrainer.create_train_step_fn signature to accept (model, optimizer, grad_accumulator, inputs, is_update_step=True, **kwargs) matching Tunix PeftTrainer and handle conditional updates when gradient accumulation is active. - Fix Qwix LoRA dummy input generation to compute dp_size and seq_len across all partitioned mesh dimensions (data, fsdp, fsdp_transpose, expert, tensor_sequence, context) avoiding IndivisibleError under multi-device FSDP mesh sharding. - Add unit test coverage for train_step signature and lora dummy input dimensions.
There was a problem hiding this comment.
Code Review
This pull request introduces support for gradient accumulation and conditional optimizer updates in the SFT trainer, and updates LoRA initialization to dynamically compute dummy input shapes based on the mesh topology. A critical issue was identified in the gradient accumulation logic: checking the truthiness of grad_accumulator.grads can evaluate to False on the first step if it is empty or uninitialized, which would permanently bypass gradient accumulation. It is recommended to simplify this check to only verify the presence of the add method.
| if ( | ||
| grad_accumulator is not None | ||
| and hasattr(grad_accumulator, "add") | ||
| and hasattr(grad_accumulator, "grads") | ||
| and bool(getattr(grad_accumulator, "grads", None)) | ||
| ): |
There was a problem hiding this comment.
Checking bool(getattr(grad_accumulator, "grads", None)) can cause gradient accumulation to be completely bypassed. If grad_accumulator.grads is initialized to None or is empty on the first step, this condition evaluates to False. As a result, the code will fall back to the else block, directly updating the optimizer and never calling grad_accumulator.add(grads). This means gradient accumulation will be permanently disabled. To fix this, simplify the condition to only check if grad_accumulator is not None and has the add method.
if grad_accumulator is not None and hasattr(grad_accumulator, "add"):
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
…sh to allow dynamic auto-sharding
5731a07 to
36c76c5
Compare
Description
This PR fixes multiple post-training regressions affecting Tunix SFT and Qwix LoRA fine-tuning in MaxText:
Tunix
is_update_stepsignature mismatch inMaxTextPeftTrainer:PeftTrainer.train()passes(model, optimizer, grad_accumulator)as partial arguments and callstrain_step(inputs, is_update_step=...).MaxTextPeftTrainer.create_train_step_fn()had an outdated signature(model, optimizer, inputs, grad_accumulator=None)which causedTypeError: train_step() got an unexpected keyword argument 'is_update_step'across all Tunix SFT workloads (gemma3-4b.sft,gpt-oss-20b.sft,llama3_1_70b.sft).(model, optimizer, grad_accumulator, inputs, is_update_step=True, **kwargs)and added support for conditional/accumulated optimizer updates when gradient accumulation is active.Qwix LoRA Sharding
IndivisibleErroron multi-device FSDP meshes:lora_utils.apply_lora_to_modelgenerated dummy tracing inputs assuming batch sizedp_size = mesh.shape['data'](defaulting to 1 whendata=1).v5p-128withfsdp=64), JAX sharding checks failed withIndivisibleErrorbecause array dimension 0 (batch size 1) was not evenly divisible by the partition factor (64).dp_sizeto compute the product of all data-parallel mesh axes (data,fsdp,fsdp_transpose,expert) andseq_lento compute the product of sequence-parallel axes (tensor_sequence,context).Tests
tests/post_training/unit/train_sft_test.pyandtests/post_training/unit/lora_utils_test.py.codespell,pylint,pyink) pass cleanly.Checklist
gemini-reviewlabel.