@@ -37,7 +37,15 @@ def __init__(
3737 self .place = place
3838 self .granularity = granularity .value if isinstance (granularity , Enum ) else granularity
3939 self .quantizer = create_quantizer (
40- self .k_init , self .i_init , self .f_init , self .overflow , self .round_mode , self .use_hgq , self .is_data , place
40+ self .k_init ,
41+ self .i_init ,
42+ self .f_init ,
43+ self .overflow ,
44+ self .round_mode ,
45+ self .use_hgq ,
46+ self .is_data ,
47+ place ,
48+ granularity = self .granularity ,
4149 )
4250 self .is_pretraining = True
4351 self .hgq_gamma = hgq_gamma
@@ -205,14 +213,41 @@ def get_config(self):
205213 return config
206214
207215
208- def create_hgq_parameters_quantizer (k , i , f , overflow , round_mode , place , gamma = 1e-8 ):
216+ def axis_kwargs_for_granularity (granularity , is_data ):
217+ """Translate a granularity into HGQ's (mutually exclusive) homogeneous/heterogeneous axis spec.
218+
219+ HGQ only supports per_tensor and per_weight from the granularity enum:
220+ - per_tensor: nothing varies -> heterogeneous_axis=() (one bitwidth for the whole tensor)
221+ - per_weight: every element varies. For data we keep the batch axis (0) homogeneous via
222+ homogeneous_axis=(0,); for weights nothing is shared via homogeneous_axis=().
223+
224+ per_channel is intentionally NOT supported for HGQ (the channel axis is layout-dependent, so we
225+ don't guess it).
226+ """
227+ if granularity == "per_tensor" :
228+ return {"heterogeneous_axis" : ()}
229+ if granularity == "per_weight" :
230+ return {"homogeneous_axis" : (0 ,) if is_data else ()}
231+ if granularity == "per_channel" :
232+ raise ValueError ("per_channel granularity is not supported for HGQ. Use 'per_tensor' or 'per_weight'." )
233+ raise ValueError (f"Unsupported granularity: { granularity } " )
234+
235+
236+ def create_hgq_parameters_quantizer (k , i , f , overflow , round_mode , place , axis_kwargs , gamma = 1e-8 ):
209237 quantizer_config = QuantizerConfig (
210- q_type = "kif" , place = place , k0 = k , i0 = i , f0 = f , overflow_mode = overflow , round_mode = round_mode , homogeneous_axis = ()
238+ q_type = "kif" ,
239+ place = place ,
240+ k0 = k ,
241+ i0 = i ,
242+ f0 = f ,
243+ overflow_mode = overflow ,
244+ round_mode = round_mode ,
245+ ** axis_kwargs ,
211246 )
212247 return HGQQuantizer (config = quantizer_config )
213248
214249
215- def create_hgq_data_quantizer (k , i , f , overflow , round_mode , gamma = 1e-8 ):
250+ def create_hgq_data_quantizer (k , i , f , overflow , round_mode , axis_kwargs , gamma = 1e-8 ):
216251 quantizer_config = QuantizerConfig (
217252 q_type = "kif" ,
218253 place = "datalane" ,
@@ -221,16 +256,19 @@ def create_hgq_data_quantizer(k, i, f, overflow, round_mode, gamma=1e-8):
221256 f0 = f ,
222257 overflow_mode = overflow ,
223258 round_mode = round_mode ,
224- homogeneous_axis = ( 0 ,) ,
259+ ** axis_kwargs ,
225260 )
226261 return HGQQuantizer (config = quantizer_config )
227262
228263
229- def create_quantizer (k , i , f , overflow , round_mode , is_heterogeneous , is_data , place = "datalane" , gamma = 1e-8 ):
264+ def create_quantizer (
265+ k , i , f , overflow , round_mode , is_heterogeneous , is_data , place = "datalane" , granularity = "per_weight" , gamma = 1e-8
266+ ):
230267 if is_heterogeneous :
268+ axis_kwargs = axis_kwargs_for_granularity (granularity , is_data )
231269 if is_data :
232- return create_hgq_data_quantizer (k , i , f , overflow , round_mode , gamma = gamma )
270+ return create_hgq_data_quantizer (k , i , f , overflow , round_mode , axis_kwargs , gamma = gamma )
233271 else :
234- return create_hgq_parameters_quantizer (k , i , f , overflow , round_mode , place , gamma = gamma )
272+ return create_hgq_parameters_quantizer (k , i , f , overflow , round_mode , place , axis_kwargs , gamma = gamma )
235273 else :
236274 return get_fixed_quantizer (round_mode = round_mode , overflow_mode = overflow )
0 commit comments