2525from fastdeploy .model_executor .layers .quantization .quant_base import QuantMethodBase
2626from fastdeploy .model_executor .utils import (
2727 default_weight_loader ,
28+ h2d_copy ,
29+ process_weight_transpose ,
2830 set_weight_attrs ,
2931 slice_fn ,
3032)
@@ -43,24 +45,36 @@ def create_weights(self, layer: nn.Layer, **extra_weight_attrs):
4345 - output_dim: determines whether the split is applied along the output dimension (rows) or input dimension (columns)
4446 - weight_loader: a callable or method responsible for loading the weight data
4547 """
48+ self .model_format = extra_weight_attrs .get ("model_format" )
49+ self .weight_shape = (
50+ layer .weight_shape [::- 1 ] if extra_weight_attrs .get ("model_format" ) == "torch" else layer .weight_shape
51+ )
52+
4653 layer .weight = layer .create_parameter (
47- shape = layer .weight_shape ,
54+ shape = self .weight_shape ,
4855 dtype = layer .weight_dtype ,
4956 is_bias = False ,
5057 default_initializer = paddle .nn .initializer .Constant (0 ),
5158 )
5259 split_axis = extra_weight_attrs .get ("split_axis" )
5360 if hasattr (layer , "nranks" ) and layer .nranks > 0 :
5461 _set_var_distributed (layer .weight , split_axis = split_axis )
62+
63+ if self .model_format == "torch" and "output_dim" in extra_weight_attrs :
64+ extra_weight_attrs ["output_dim" ] = not extra_weight_attrs ["output_dim" ]
65+
5566 set_weight_attrs (
5667 layer .weight ,
5768 {
5869 ** extra_weight_attrs ,
5970 "weight_loader" : extra_weight_attrs .get ("weight_loader" , default_weight_loader (layer .fd_config )),
60- "weight_need_transpose" : extra_weight_attrs .get ("model_format" ) == "torch" ,
6171 },
6272 )
6373
74+ def process_weights_after_loading (self , layer ):
75+ if self .model_format == "torch" :
76+ process_weight_transpose (layer , "weight" )
77+
6478 def process_loaded_weights (self , layer , weights ) -> None :
6579 # mlp.gate.weight is precision-sensitive, so we cast it to float32 for computation
6680 if layer .weight .dtype != weights .dtype :
@@ -165,7 +179,7 @@ def __init__(
165179 if self .with_bias :
166180 self .bias = self .create_parameter (
167181 shape = [self .output_size ],
168- dtype = self ._dtype ,
182+ dtype = self .weight_dtype ,
169183 is_bias = True ,
170184 )
171185 setattr (
@@ -262,6 +276,7 @@ def __init__(
262276 skip_quant : bool = False ,
263277 weight_dtype : str = "" ,
264278 weight_key : str = "" ,
279+ model_format : Optional [str ] = None ,
265280 ):
266281 """
267282 Initializes a replicated linear layer.
@@ -296,7 +311,7 @@ def __init__(
296311 weight_loader = (
297312 self .weight_loader if hasattr (self , "weight_loader" ) else default_weight_loader (self .fd_config )
298313 ),
299- model_format = fd_config .model_config .model_format ,
314+ model_format = fd_config .model_config .model_format if model_format is None else model_format ,
300315 )
301316
302317
@@ -344,10 +359,8 @@ def __init__(
344359
345360 def weight_loader (self , param , loaded_weight , loaded_shard_id : Optional [str ] = None ):
346361 weight_need_transpose = getattr (param , "weight_need_transpose" , False )
347- loaded_weight = get_tensor (loaded_weight )
348-
349362 if weight_need_transpose :
350- loaded_weight = loaded_weight .transpose ([1 , 0 ])
363+ loaded_weight = get_tensor ( loaded_weight ) .transpose ([1 , 0 ])
351364
352365 assert loaded_shard_id in ["q_a" , "kv_a" ]
353366 if not param ._is_initialized ():
@@ -373,7 +386,9 @@ def weight_loader(self, param, loaded_weight, loaded_shard_id: Optional[str] = N
373386 loaded_weight = loaded_weight .view (param .dtype )
374387 else :
375388 loaded_weight = loaded_weight .cast (param .dtype )
376- param .copy_ (loaded_weight , False )
389+ # (bukejiyu) After this fix, the early H2D copy for non-GPU devices is no longer needed and can be safely removed.
390+ loaded_weight = get_tensor (loaded_weight )
391+ h2d_copy (param , loaded_weight )
377392
378393
379394class ColumnParallelLinear (LinearBase ):
@@ -393,7 +408,7 @@ def __init__(
393408 with_bias : bool = False ,
394409 add_bias : bool = False ,
395410 skip_quant : bool = False ,
396- weight_dtype = "" ,
411+ weight_dtype : str = "" ,
397412 ):
398413 """
399414 Initializes a linear layer and provides additional parameters required for inference and quantization.
@@ -493,6 +508,7 @@ def __init__(
493508 )
494509
495510 def weight_loader (self , param , loaded_weight , loaded_shard_id : Optional [str ] = None ):
511+ # for xpu and other backend
496512 weight_need_transpose = getattr (param , "weight_need_transpose" , False )
497513 output_dim = getattr (param , "output_dim" , None )
498514 assert output_dim is not None
@@ -522,7 +538,7 @@ def weight_loader(self, param, loaded_weight, loaded_shard_id: Optional[str] = N
522538 loaded_weight = get_tensor (loaded_weight )
523539 loaded_weight = loaded_weight .transpose ([1 , 0 ])
524540 # Tensor parallelism splits the weight along the output_dim
525- if self .nranks != 1 :
541+ if self .nranks > 1 and output_dim is not None :
526542 dim = - 1 if output_dim else 0
527543 if isinstance (loaded_weight , (np .ndarray , paddle .Tensor )):
528544 size = loaded_weight .shape [dim ]
@@ -532,7 +548,6 @@ def weight_loader(self, param, loaded_weight, loaded_shard_id: Optional[str] = N
532548 shard_offset = self .local_rank * block_size
533549 shard_size = (self .local_rank + 1 ) * block_size
534550 loaded_weight = slice_fn (loaded_weight , output_dim , start = shard_offset , end = shard_size )
535- loaded_weight = get_tensor (loaded_weight )
536551 if not param ._is_initialized ():
537552 param .initialize ()
538553 param_shard_size = output_size // 2
@@ -553,7 +568,8 @@ def weight_loader(self, param, loaded_weight, loaded_shard_id: Optional[str] = N
553568 loaded_weight = loaded_weight .view (param .dtype )
554569 else :
555570 loaded_weight = loaded_weight .cast (param .dtype )
556- param .copy_ (loaded_weight , False )
571+
572+ h2d_copy (param , loaded_weight )
557573
558574 def load_state_dict (self , state_dict : dict ):
559575 """
@@ -589,7 +605,19 @@ class QKVParallelLinear(ColumnParallelLinear):
589605 QKVParallelLinear Layer.
590606 """
591607
592- def __init__ (self , fd_config , prefix , with_bias = False , add_bias = True ):
608+ def __init__ (
609+ self ,
610+ fd_config ,
611+ prefix ,
612+ with_bias = False ,
613+ add_bias = True ,
614+ num_heads : Optional [int ] = None ,
615+ kv_num_heads : Optional [int ] = None ,
616+ hidden_size : Optional [int ] = None ,
617+ head_dim : Optional [int ] = None ,
618+ skip_quant : bool = False ,
619+ weight_dtype : str = "" ,
620+ ):
593621 """
594622 Initialize the QKV Linear layer with given parameters.
595623
@@ -599,11 +627,15 @@ def __init__(self, fd_config, prefix, with_bias=False, add_bias=True):
599627 Can be arbitrarily named.
600628 with_bias (bool): Whether to include bias or not. Defaults to False.
601629 add_bias (bool): Whether to add bias in the current layer or in the pre/post layer. Defaults to True.
630+ num_heads (Optional[int]): Number of attention heads in the model.
631+ kv_num_heads (Optional[int]): Number of key/value heads, used for multi-query or grouped-query attention.
632+ hidden_size (Optional[int]): Total hidden layer dimension, typically the embedding size.
633+ head_dim (Optional[int]): Size of each attention head, usually computed as hidden_size divided by num_heads.
602634 """
603- self .num_heads = fd_config .model_config .num_attention_heads
604- self .kv_num_heads = fd_config .model_config .num_key_value_heads
605- self .hidden_size = fd_config .model_config .hidden_size
606- self .head_dim = fd_config .model_config .head_dim
635+ self .num_heads = fd_config .model_config .num_attention_heads if num_heads is None else num_heads
636+ self .kv_num_heads = fd_config .model_config .num_key_value_heads if kv_num_heads is None else kv_num_heads
637+ self .hidden_size = fd_config .model_config .hidden_size if hidden_size is None else hidden_size
638+ self .head_dim = fd_config .model_config .head_dim if head_dim is None else head_dim
607639 self .nranks = fd_config .parallel_config .tensor_parallel_size
608640 self .local_rank = fd_config .parallel_config .tensor_parallel_rank
609641 self .num_heads_per_rank = divide (self .num_heads , self .nranks )
@@ -623,6 +655,8 @@ def __init__(self, fd_config, prefix, with_bias=False, add_bias=True):
623655 output_size = output_size ,
624656 with_bias = with_bias ,
625657 add_bias = add_bias ,
658+ skip_quant = skip_quant ,
659+ weight_dtype = weight_dtype ,
626660 )
627661
628662 def _get_shard_size_mapping (self , loaded_shard_id : str , head_dim : int ):
@@ -664,15 +698,13 @@ def weight_loader(self, param, loaded_weight, loaded_shard_id: Optional[str] = N
664698 loaded_weight = get_tensor (loaded_weight )
665699 loaded_weight = loaded_weight .transpose ([1 , 0 ])
666700 # Tensor parallelism splits the weight along the output_dim
667- if self .nranks != 1 :
701+ if self .nranks > 1 and output_dim is not None :
668702 block_size = self ._get_shard_size_mapping (loaded_shard_id , head_dim )
669703 shard_id = self .local_rank if loaded_shard_id == "q" else self .local_rank // self .num_kv_head_replicas
670704 shard_offset = shard_id * block_size
671705 shard_size = block_size
672706 loaded_weight = slice_fn (loaded_weight , output_dim , start = shard_offset , end = shard_offset + shard_size )
673707
674- loaded_weight = get_tensor (loaded_weight )
675-
676708 if not param ._is_initialized ():
677709 param .initialize ()
678710
@@ -700,7 +732,7 @@ def weight_loader(self, param, loaded_weight, loaded_shard_id: Optional[str] = N
700732 loaded_weight = loaded_weight .view (param .dtype )
701733 else :
702734 loaded_weight = loaded_weight .cast (param .dtype )
703- param . copy_ ( loaded_weight , False )
735+ h2d_copy ( param , loaded_weight )
704736
705737 def load_weight (self , state_dict : dict ):
706738 """
@@ -798,7 +830,7 @@ def __init__(
798830 add_bias : bool = False ,
799831 reduce_results : bool = True ,
800832 skip_quant : bool = False ,
801- weight_dtype = "" ,
833+ weight_dtype : str = "" ,
802834 layer_id : int = - 1 ,
803835 ):
804836 """
@@ -857,10 +889,6 @@ def __init__(
857889 ),
858890 model_format = fd_config .model_config .model_format ,
859891 )
860- if self .nranks > 0 :
861- if self .with_bias :
862- # col parallel
863- _set_var_distributed (self .bias , split_axis = 0 )
864892
865893 self .reduce_results = reduce_results
866894
0 commit comments