Repository navigation
feat(model): dp balance - #355
Merged
meichangsu1 merged 8 commits intoNov 3, 2026
Merged
Conversation
… packed inputs - Add twinkle.model.plan_dp_balance: permute a batch before slice_dp so every DP rank gets a similar estimated cost. Each rank's cost is simulated with the model's own micro-batch planner (fixed or dynamic batching, common micro-batch count across ranks), padded micro-batches cost rows * w(longest) and packed ones sum(w(s)), with w(s) = 6*h*s + s^2. Candidates: original order, equal-size Karmarkar-Karp, and a length snake; the original order is kept unless the slowest rank gets lighter. Per-rank sample counts stay the same; DPBalancePlan.apply() reorders aligned fields. Adds dp_balance/* metrics, including micro-batch count and padding ratio. - micro_batch: add plan_micro_batches_for_lengths and equal-size KK. - Fix forward_only with padding-free inputs: pass use_cache=False so Transformers keeps detecting packed sequences in eval mode. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>EOF git log --oneline -2
…mpletions
A dataset-encoded Qwen3.5 prompt stores the processor's [1, L] mm_token_type_ids as a nested list.
swift's append_and_finalize extends Python lists flat, giving a ragged [[0] * L, 0, 0, ...] that the
input processor cannot tensorize ("not a sequence"). Convert nested-list token fields to arrays first
so they are extended to [1, L + n], as numpy and torch fields already are.
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Uses argparse (no twinkle.cli), scores rewards on new_state.messages, and installs the fla kernels on NPU for packed inputs through apply_patch. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Keep the sequence-parallel context from dev-swift-v5 around forward_only's model call, with use_cache=False inside it. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
meichangsu1
reviewed
Oct 30, 2026
| return DPBalancePlan(order=identity) | ||
|
|
||
| # Ties keep the earlier candidate, so the batch is only permuted when the slowest rank gets lighter. | ||
| strategy = min(estimates, key=lambda name: (max(estimates[name][1].workloads), estimates[name][1].micro_batches)) |
Collaborator
There was a problem hiding this comment.
batch 不能被 DP 数整除时,重排会改变 GRPO 梯度权重
Collaborator
Author
There was a problem hiding this comment.
不能被 DP 数整除时,已改为不重排,保持原顺序
| with self.sp_strategy.context() if self.sp_strategy is not None else contextlib.nullcontext(): | ||
| outputs = self.model(**inputs) | ||
| # In eval mode use_cache defaults to True, and Transformers skips detecting | ||
| # padding-free packed sequences whenever a KV cache exists. |
Collaborator
There was a problem hiding this comment.
这里为什么要use_cache=False
Collaborator
Author
There was a problem hiding this comment.
padding-free 时多条样本拼成一行,没有 attention_mask,样本边界靠 position_ids 区分,transformers 只有在 past_key_values is None 时才按 position_ids 切分。
forward_only 在 eval 模式下,默认use_cache=True,模型内部会 past_key_values = DynamicCache(上面的条件不成立)导致整行按一条长序列的普通 causal mask 计算。forward_only 用不到 KV cache。
GRPOLoss averages over a rank's samples and DP averages the ranks, so a sample weighs 1 / (dp_size * rank_size). When get_slice gives some ranks one sample more, moving samples between ranks changes their weights, so plan_dp_balance now returns the original order there. This also drops the placeholders and size sorting that only uneven splits needed. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
The uneven-batch check ran after the group-size check, so a grouped batch whose size is not a multiple of dp_size raised ValueError instead of keeping its order as documented. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Without gradient checkpointing, use_cache stays True in the training forward, so Transformers skips detecting padding-free packed sequences and packed samples attend to each other. Pass use_cache=False as forward_only already does. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Make the common micro-batch count test fail if ranks are estimated without it: use padded rows where the rank 1 cost changes. - Reuse the default fla kernel choice in the cookbook. - Reuse micro_batch._batch_cost for computed tokens. - Drop the unused metric_prefix option. - Add the copyright header to test_contract_append.py. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2 of 4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR type
PR information
In RL training, every step waits for the slowest DP rank. Rollout lengths vary a lot, so the contiguous split
slice_dpmakes is often uneven. This PR adds an opt-in planner that reorders a mini-batch on the driver, beforeforward_backward, so that each rank gets a similar workload.Feature
plan_dp_balance(...)returns aDPBalancePlan; apply it withplan.apply()to every sample-aligned field (inputs,old_logps,advantages, ...).slice_dpstay unchanged, so the gradient is unchanged for per-sequence-mean losses such asGRPOLoss. Addsdp_balance/*metrics.cookbook/rl/grpo/dp_balance_grpo.{py,sh}example.Bug fixes
TypeError: not a sequencewith Qwen3.5 / Qwen-VL rollouts.dataset.encodestoresmm_token_type_idsas a nested[1, L]list, and swift'sappend_and_finalizeextends it flat, so its length no longer matchesinput_ids. The twinkle wrapper now converts it to an array first.forward_only. In eval modeuse_cacheis True and Transformers skips packed-sequence detection.forward_onlynow passesuse_cache=False.Experiment results
Environment: 4 × Ascend 910B3 (2 for training, 2 for vLLM), CANN 9.1.0, Python 3.12, torch 2.10.0 / torch_npu 2.10.0.post4, transformers 5.14.1, vLLM 0.26.0 / vllm-ascend 0.26.0rc2, flash-linear-attention 0.5.2.
Setup: Qwen3.5-4B GRPO on GSM8K, LoRA, FSDP2 with DP=2, dynamic batching, 50 steps. Each layout runs with
balance_batchoff and on, using the same seed.