def METHOD_NAME(self, params_grads):
    normal_params_grads = []
    moe_params_grads = []
    # separate moe params from normal params
    if self.moe_group is not None and self.moe_group.nranks > 1:
        for p, g in params_grads:
            if self.is_expert_param_func(p):
                moe_params_grads.append((p, g))
            else:
                normal_params_grads.append((p, g))
    else:
        normal_params_grads = params_grads
    # why to return sum_dtype?
    # we will call `get_l2_norm_pow` twice and the precisions may be different.
    # For convenience and simplification, we use sum_dtype directly instead of global_norm_var_normal.dtype
    global_norm_var_normal, sum_dtype = self.get_l2_norm_pow(normal_params_grads)
    if global_norm_var_normal is not None:
        paddle.distributed.all_reduce(
            global_norm_var_normal, op=paddle.distributed.ReduceOp.SUM, group=self.moe_group
        )
    global_norm_var_moe = None
    if len(moe_params_grads) > 0:
        global_norm_var_moe, _ = self.get_l2_norm_pow(moe_params_grads, sum_dtype)
        if global_norm_var_moe is not None:
            paddle.distributed.all_reduce(
                global_norm_var_moe, op=paddle.distributed.ReduceOp.SUM, group=self.moe_group
            )
    if global_norm_var_normal is None and global_norm_var_moe is None:
        return params_grads
    elif global_norm_var_normal is None:
        global_norm_var = global_norm_var_moe
    elif global_norm_var_moe is None:
        global_norm_var = global_norm_var_normal
    else:
        if global_norm_var_normal.dtype != global_norm_var_moe.dtype:
            # compared with normal norm, moe norm is the later one,
            # so its precision is no lower than normal norm
            global_norm_var_normal = global_norm_var_normal.astype(global_norm_var_moe.dtype)
        global_norm_var = global_norm_var_normal + global_norm_var_moe
    params_and_grads = []
    global_norm_var = paddle.sqrt(global_norm_var)
    max_global_norm = paddle.full(shape=[1], dtype=global_norm_var.dtype, fill_value=self.clip_norm)
    clip_var = paddle.maximum(x=max_global_norm, y=paddle.maximum(x=global_norm_var, y=max_global_norm))
    for p, g in params_grads:
        if g is None:
            continue
        if getattr(p, "need_clip", True) is False:
            params_and_grads.append((p, g))
            continue
        # TODO(wangxi): use inplace elementwise_mul
        clip_input = clip_var.astype("float16") if g.dtype == core.VarDesc.VarType.FP16 else clip_var
        new_grad = paddle.multiply(x=g, y=clip_input)
        params_and_grads.append((p, new_grad))
    return params_and_grads