2222
2323import contextlib
2424import math
25- import os
26- from typing import Dict , List , Optional , OrderedDict , Tuple , Union
25+ from typing import List , Optional , Tuple , Union
2726
2827import habana_frameworks .torch .core as htcore
2928import torch
4241 MixtralDecoderLayer ,
4342 MixtralForCausalLM ,
4443 MixtralModel ,
45- MixtralSparseMoeBlock ,
4644 apply_rotary_pos_emb ,
4745 load_balancing_loss_func ,
4846)
@@ -451,35 +449,46 @@ def gaudi_mixtral_block_sparse_moe_forward(self, hidden_states: torch.Tensor) ->
451449 return final_hidden_states , router_logits
452450
453451
454- class DynamicFusedMoE (nn .Module ):
455- """DynamicFusedMoE layer for MoE models.
456- Based on implementation from vllm:
457- https://github.com/HabanaAI/vllm-fork/blob/84922944da5b65fa43bbdc465650911cbef9de72/vllm/hpu/ops.py#L282"""
458452
459- def __init__ (self , num_total_experts ):
460- super ().__init__ ()
461- self .num_total_experts = num_total_experts
453+ def gaudi_mixtral_block_dynamic_moe_forward (self , hidden_states : torch .Tensor ) -> Tuple [torch .Tensor , torch .Tensor ]:
454+ batch_size , sequence_length , hidden_dim = hidden_states .shape
455+ original_shape = hidden_states .shape
456+ hidden_states = hidden_states .view (- 1 , hidden_dim )
457+ # router_logits: (batch * sequence_length, n_experts)
458+ router_logits = self .gate (hidden_states )
462459
463- def forward (
464- self , hidden_states : torch .Tensor , w13 : torch .Tensor , w2 : torch .Tensor , score : torch .Tensor , topk : int
465- ) -> torch .Tensor :
466- routing_weights , selected_experts = calculate_routing_tensors (score , topk , hidden_states .dtype )
467- # pre-processing for custom op inputs
468- experts_range = range (self .num_total_experts )
469- w13_list = [w13 [i , :, :].squeeze () for i in experts_range ]
470- w2_list = [w2 [i , :, :].squeeze () for i in experts_range ]
471- final_hidden_states = torch .ops .hpu .mixture_of_experts (
472- hidden_states = hidden_states ,
473- expert_routing_table = selected_experts ,
474- router_weights = routing_weights ,
475- w12 = w13_list ,
476- w3 = w2_list ,
477- permuted_weights = True ,
478- activation = "silu" ,
479- experts_min = 0 ,
480- experts_max = 7 ,
481- )
482- return final_hidden_states .view (- 1 , hidden_states .shape [1 ])
460+ if is_deepspeed_available () and (not self .training ):
461+ from deepspeed import comm as dist
462+
463+ if dist .is_initialized ():
464+ output_tensors = [router_logits .clone () for _ in range (dist .get_world_size ())]
465+ dist .all_gather (output_tensors , router_logits )
466+ router_logits = torch .cat (output_tensors , dim = 1 )
467+
468+ routing_weights , selected_experts = calculate_routing_tensors (router_logits , self .top_k , hidden_states .dtype )
469+ # pre-processing for custom op inputs
470+ w1_list = [expert .w1 .weight for expert in self .experts ]
471+ w2_list = [expert .w2 .weight for expert in self .experts ]
472+ w3_list = [expert .w3 .weight for expert in self .experts ]
473+
474+ final_hidden_states = torch .ops .hpu .mixture_of_experts (
475+ hidden_states = hidden_states ,
476+ expert_routing_table = selected_experts ,
477+ router_weights = routing_weights ,
478+ w1 = w1_list ,
479+ w3 = w2_list ,
480+ w2 = w3_list ,
481+ permuted_weights = True ,
482+ activation = "silu" ,
483+ experts_min = 0 ,
484+ experts_max = 7 ,
485+ )
486+ if is_deepspeed_available () and (not self .training ):
487+ from deepspeed import comm as dist
488+ if dist .is_initialized ():
489+
490+ dist .all_reduce (final_hidden_states )
491+ return final_hidden_states .view (original_shape ), router_logits
483492
484493
485494def calculate_routing_tensors (
@@ -493,142 +502,6 @@ def calculate_routing_tensors(
493502 return routing_weights , selected_experts
494503
495504
496- class FusedMoE (nn .Module ):
497- def __init__ (
498- self ,
499- config : MixtralConfig ,
500- tp_size : int = 1 ,
501- params_dtype : Optional [torch .dtype ] = None ,
502- ):
503- super ().__init__ ()
504- if params_dtype is None :
505- params_dtype = torch .get_default_dtype ()
506-
507- self .top_k = config .num_experts_per_tok
508- self .num_experts = config .num_local_experts
509- self .tp_size = tp_size
510-
511- self .intermediate_size = config .intermediate_size
512- self .intermediate_size_per_partition = config .intermediate_size // self .tp_size
513- self .hpu_fused_moe = DynamicFusedMoE (self .num_experts )
514-
515- # Fused gate_up_proj (column parallel)
516- self .w13_weight = nn .Parameter (
517- torch .rand (
518- self .num_experts ,
519- 2 * self .intermediate_size_per_partition ,
520- config .hidden_size ,
521- dtype = params_dtype ,
522- ).multiply (config .initializer_range )
523- )
524- # down_proj (row parallel)
525- self .w2_weight = nn .Parameter (
526- torch .rand (
527- self .num_experts ,
528- config .hidden_size ,
529- self .intermediate_size_per_partition ,
530- dtype = params_dtype ,
531- ).multiply (config .initializer_range )
532- )
533-
534- def forward (self , hidden_states : torch .Tensor , router_logits : torch .Tensor ) -> torch .Tensor :
535- final_hidden_states = self .hpu_fused_moe (
536- hidden_states , self .w13_weight , self .w2_weight , router_logits , self .top_k
537- )
538- if self .tp_size > 1 :
539- from deepspeed import comm as dist
540-
541- dist .all_reduce (final_hidden_states )
542- return final_hidden_states
543-
544-
545- class GaudiDynamicMoeBlock (MixtralSparseMoeBlock ):
546- def __init__ (self , config : MixtralConfig ):
547- super ().__init__ (config )
548- self .tp_size = 1
549- if is_deepspeed_available ():
550- from deepspeed import comm as dist
551-
552- if dist .is_initialized ():
553- self .tp_size = dist .get_world_size ()
554- self .intermediate_size_per_partition = config .intermediate_size // self .tp_size
555- self .experts = FusedMoE (config , self .tp_size )
556-
557- def forward (self , hidden_states : torch .Tensor ) -> Tuple [torch .Tensor , torch .Tensor ]:
558- _ , _ , hidden_dim = hidden_states .shape
559- orig_shape = hidden_states .shape
560-
561- hidden_states = hidden_states .view (- 1 , hidden_dim )
562- # router_logits: (batch * sequence_length, n_experts)
563- router_logits = self .gate (hidden_states )
564- if is_deepspeed_available () and (not self .training ):
565- from deepspeed import comm as dist
566-
567- if dist .is_initialized ():
568- output_tensors = [router_logits .clone () for _ in range (dist .get_world_size ())]
569- dist .all_gather (output_tensors , router_logits )
570- router_logits = torch .cat (output_tensors , dim = 1 )
571-
572- final_hidden_states = self .experts (hidden_states , router_logits )
573- return final_hidden_states .view (orig_shape ), router_logits
574-
575- def _load_from_state_dict (
576- self ,
577- state_dict : OrderedDict [str , torch .Tensor ],
578- prefix : str ,
579- local_metadata : Dict [str , str ],
580- strict : bool ,
581- missing_keys : List [str ],
582- unexpected_keys : List [str ],
583- error_msgs : List [str ],
584- ) -> None :
585- gate_up = ["w1" , "w3" ]
586- gate_down_up = ["w1" , "w2" , "w3" ]
587- params_dict = dict (self .experts .named_parameters ())
588- for name , loaded_weight in state_dict .items ():
589- if "rotary_emb.inv_freq" in name or not name .startswith (prefix ) or name .endswith ("gate.weight" ):
590- continue
591- # normal flow, as using normal model
592- if len (name .strip (prefix ).split ("." )) == 4 :
593- _ , expert_id , weight_name , _ = name .strip (prefix ).split ("." )
594- param_name = "w13_weight" if weight_name in gate_up else "w2_weight"
595- shard_id = gate_down_up .index (weight_name )
596- expert_id = int (expert_id )
597- param_data = params_dict [param_name ].data
598-
599- tp_rank = 0
600- if self .tp_size > 1 :
601- from deepspeed import comm as dist
602-
603- tp_rank = dist .get_rank ()
604-
605- shard_size = self .intermediate_size_per_partition
606- shard = slice (tp_rank * shard_size , (tp_rank + 1 ) * shard_size )
607-
608- # w1, gate_proj case: Load into first shard of w13.
609- if shard_id == 0 :
610- param_data [expert_id , 0 :shard_size , :] = loaded_weight [shard , :]
611- # w3, up_proj case: Load into second shard of w13.
612- elif shard_id == 2 :
613- param_data [expert_id , shard_size : 2 * shard_size , :] = loaded_weight [shard , :]
614- # w2, down_proj case: Load into only shard of w2.
615- elif shard_id == 1 :
616- param_data [expert_id , :, :] = loaded_weight [:, shard ]
617- else :
618- raise ValueError (f"Shard id must be in [0,1,2] but got { shard_id } " )
619- #flow prepared for tests
620- elif len (name .strip (prefix ).split ("." )) == 2 :
621- if name .endswith ("w13_weight" ):
622- self .experts .w13_weight .data = loaded_weight
623- elif name .endswith ("w2_weight" ):
624- self .experts .w2_weight .data = loaded_weight
625- else :
626- ValueError (f"Unexpected weight name: { name } " )
627- else :
628- raise ValueError (f"Unexpected weight name: { name } " )
629-
630-
631-
632505class GaudiMixtralDecoderLayer (MixtralDecoderLayer ):
633506 def __init__ (self , config : MixtralConfig , layer_idx : int ):
634507 super ().__init__ (config , layer_idx )
@@ -907,12 +780,6 @@ class GaudiMixtralForCausalLM(MixtralForCausalLM):
907780 - from step2 when enable KV cache, slice next_position_ids from position_ids base on the token_idx
908781 """
909782
910- # We don't want to raise an error for unitialized weights
911- _keys_to_ignore_on_load_missing = [
912- r"model.layers.\d+.block_sparse_moe.experts.w2_weight" ,
913- r"model.layers.\d+.block_sparse_moe.experts.w13_weight" ,
914- ]
915-
916783 def allocate_kv_cache (self , batch_size , max_seq_len , inp_seq_len ):
917784 self .model .allocate_kv_cache (batch_size , max_seq_len , inp_seq_len )
918785 self .kv_cache_len = max_seq_len
0 commit comments