@@ -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