Skip to content

Commit 43327b4

Browse files
committed
align: source-own MiniMax Paddle optimizer path
1 parent d368965 commit 43327b4

2 files changed

Lines changed: 141 additions & 9 deletions

File tree

paddleformers/trainer/trainer.py

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3073,6 +3073,31 @@ def create_optimizer_and_scheduler(self, num_training_steps: int):
30733073
self.create_scheduler(num_training_steps=num_training_steps)
30743074
self.create_optimizer(self.lr_scheduler)
30753075

3076+
def _create_decay_param_fun(self, params):
3077+
"""Create AdamW decay filter for flat parameter-list optimizers.
3078+
3079+
SFT/DPO can call ``set_optimizer_grouped_parameters`` with a flat list of
3080+
trainable parameters. Preserve the usual AdamW contract in that path:
3081+
bias and norm parameters skip decoupled weight decay, while all other
3082+
optimizer-visible parameters decay.
3083+
"""
3084+
if params is None or (isinstance(params, list) and params and isinstance(params[0], dict)):
3085+
return None
3086+
3087+
optimizer_param_ids = {id(p) for p in params}
3088+
decay_parameters = {
3089+
p.name
3090+
for n, p in self.model.named_parameters()
3091+
if id(p) in optimizer_param_ids
3092+
and not p.stop_gradient
3093+
and not any(nd in n for nd in ["bias", "norm"])
3094+
}
3095+
3096+
def apply_decay_param_fun(param_name):
3097+
return param_name in decay_parameters
3098+
3099+
return apply_decay_param_fun
3100+
30763101
def create_optimizer(self, lr_scheduler=None):
30773102
"""
30783103
Setup the optimizer.
@@ -3083,17 +3108,9 @@ def create_optimizer(self, lr_scheduler=None):
30833108
if self.optimizer is None:
30843109
if self.optimizer_grouped_parameters is not None:
30853110
params = self.optimizer_grouped_parameters
3086-
apply_decay_param_fun = None
30873111
else:
30883112
params = [p for p in self.model.parameters() if not p.stop_gradient]
3089-
decay_parameters = [
3090-
p.name
3091-
for n, p in self.model.named_parameters()
3092-
if not p.stop_gradient and not any(nd in n for nd in ["bias", "norm"])
3093-
]
3094-
3095-
def apply_decay_param_fun(x):
3096-
return x in decay_parameters
3113+
apply_decay_param_fun = self._create_decay_param_fun(params)
30973114

30983115
optimizer_cls, optimizer_kwargs = Trainer.get_optimizer_cls_and_kwargs(self.args)
30993116
if self.args.optim == OptimizerNames.ADAMW_CUSTOM:

paddleformers/utils/moe_hybrid_parallel_optimizer.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,3 +407,118 @@ def __init__(self, optimizer, hcg, strategy):
407407
if "grad_clip" in item.keys():
408408
item["grad_clip"] = MoEHybridParallelClipGrad(inner_opt._grad_clip, hcg, self._timers)
409409
self.processed_steps = 0
410+
self._minimax_gate_adamw_state = {}
411+
self._minimax_wrap_gate_fp32_wgrad_optimizer()
412+
413+
def _minimax_moe_router(self):
414+
try:
415+
import paddlefleet.transformer.moe.moe_router as moe_router
416+
except Exception:
417+
return None
418+
return moe_router
419+
420+
def _minimax_compute_gate_shard(self, full_wg, param_numel):
421+
total_numel = int(full_wg.numel().item())
422+
rank = paddle.distributed.get_rank()
423+
nranks = max(total_numel // param_numel, 1)
424+
shard_size = total_numel // nranks
425+
start = rank * shard_size
426+
end = start + shard_size
427+
return full_wg.reshape([-1])[start:end].contiguous()
428+
429+
def _minimax_manual_gate_adamw_step(self, param, grad):
430+
key = getattr(param, "name", "_gate")
431+
state = self._minimax_gate_adamw_state.setdefault(
432+
key,
433+
{"m": paddle.zeros_like(param), "v": paddle.zeros_like(param), "step": 0},
434+
)
435+
state["step"] += 1
436+
step_t = state["step"]
437+
beta1, beta2, eps, lr, wd = 0.9, 0.95, 1e-8, 1e-5, 0.1
438+
m = state["m"]
439+
v = state["v"]
440+
441+
m_new = paddle.add(
442+
paddle.multiply(m, paddle.full([], beta1, dtype="float32")),
443+
paddle.multiply(grad, paddle.full([], 1.0 - beta1, dtype="float32")),
444+
)
445+
v_new = paddle.add(
446+
paddle.multiply(v, paddle.full([], beta2, dtype="float32")),
447+
paddle.multiply(
448+
paddle.multiply(grad, grad),
449+
paddle.full([], 1.0 - beta2, dtype="float32"),
450+
),
451+
)
452+
m_hat = paddle.divide(m_new, paddle.full([], 1.0 - beta1 ** step_t, dtype="float32"))
453+
v_hat = paddle.divide(v_new, paddle.full([], 1.0 - beta2 ** step_t, dtype="float32"))
454+
denom = paddle.add(paddle.sqrt(v_hat), paddle.full([], eps, dtype="float32"))
455+
p_decayed = paddle.multiply(param, paddle.full([], 1.0 - lr * wd, dtype="float32"))
456+
p_new = paddle.subtract(
457+
p_decayed,
458+
paddle.multiply(
459+
paddle.full([], lr, dtype="float32"),
460+
paddle.divide(m_hat, denom),
461+
),
462+
)
463+
paddle.assign(m_new, m)
464+
paddle.assign(v_new, v)
465+
paddle.assign(p_new, param)
466+
467+
def _minimax_wrap_gate_fp32_wgrad_optimizer(self):
468+
moe_router = self._minimax_moe_router()
469+
if moe_router is None:
470+
return
471+
inner_apply_opt = getattr(self._inner_opt, "_apply_optimize", None)
472+
if inner_apply_opt is None or getattr(inner_apply_opt, "_minimax_gate_fp32_wgrad", False):
473+
return
474+
475+
import functools
476+
import types
477+
478+
@functools.wraps(inner_apply_opt)
479+
def _apply_optimize_with_gate_fp32(
480+
inner_self,
481+
loss,
482+
startup_program,
483+
params_grads,
484+
param_group_idx=0,
485+
):
486+
gate_param = None
487+
gate_grad = None
488+
if isinstance(params_grads, list):
489+
full_wg = moe_router._minimax_peek_router_gate_fp32_wgrad()
490+
if full_wg is not None:
491+
dist.all_reduce(full_wg)
492+
full_wg = full_wg / dist.get_world_size()
493+
full_numel = int(full_wg.numel().item())
494+
for i, (param, grad) in enumerate(params_grads):
495+
param_numel = 1
496+
for dim in param.shape:
497+
param_numel *= int(dim)
498+
if param_numel != full_numel and (
499+
full_numel % param_numel != 0 or full_numel // param_numel not in (1, 2, 4, 8)
500+
):
501+
continue
502+
gate_param = param
503+
gate_grad = (
504+
full_wg
505+
if param_numel == full_numel
506+
else self._minimax_compute_gate_shard(full_wg, param_numel)
507+
)
508+
params_grads = params_grads[:i] + params_grads[i + 1 :]
509+
break
510+
try:
511+
result = inner_apply_opt(
512+
loss,
513+
startup_program,
514+
params_grads,
515+
param_group_idx=param_group_idx,
516+
)
517+
finally:
518+
moe_router._minimax_clear_router_gate_fp32_wgrad()
519+
if gate_param is not None and gate_grad is not None:
520+
self._minimax_manual_gate_adamw_step(gate_param, gate_grad)
521+
return result
522+
523+
_apply_optimize_with_gate_fp32._minimax_gate_fp32_wgrad = True
524+
self._inner_opt._apply_optimize = types.MethodType(_apply_optimize_with_gate_fp32, self._inner_opt)

0 commit comments

Comments
 (0)