Skip to content

Commit a7bd1d9

Browse files
jinzhen-lincodex
andauthored
fix(schema): preserve tensor and group scales across shards (#142)
Signed-off-by: jinzhen.ljz <jinzhen.ljz@antgroup.com> Co-authored-by: Codex (GPT-6) <codex@openai.com>
1 parent f35c5ff commit a7bd1d9

6 files changed

Lines changed: 40 additions & 24 deletions

File tree

‎humming/schema/base.py‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,15 +162,20 @@ def _may_process_global_scale(
162162
shape_k_stacks: list[int],
163163
num_experts: int | None = None,
164164
target_group_size: int | None = None,
165-
force_repeat: int = False,
165+
force_repeat: bool = False,
166166
):
167167
assert len(shape_n_stacks) == 1 or len(shape_k_stacks) == 1
168168

169169
scale = scale.view(num_experts or 1, -1)
170+
stack_size = max(len(shape_n_stacks), len(shape_k_stacks))
171+
assert scale.size(1) in (1, stack_size)
170172

171173
if (scale == scale[:, [0]]).all() and not force_repeat:
172174
return scale[:, 0]
173-
elif len(shape_n_stacks) > 1:
175+
176+
# A single scale per expert is shared by all of its stacked shards.
177+
scale = scale.expand(-1, stack_size)
178+
if len(shape_n_stacks) > 1:
174179
shape_n_repeats = torch.tensor(shape_n_stacks)
175180
target_group_size = target_group_size or sum(shape_k_stacks)
176181
shape_k_repeats = torch.tensor([sum(shape_k_stacks) // target_group_size])

‎humming/schema/compressed_tensors.py‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ def _convert_humming(
221221
weight_scale = weight_scale.view(torch.float8_e8m0fnu)
222222
elif self.format.startswith("nvfp4"):
223223
weight_scale = weight_scale.view(torch.float8_e4m3fn)
224-
else:
224+
elif self.strategy != "tensor":
225225
weight_scale = weight_scale.to(param_dtype)
226226

227227
if self.strategy in ["group", "tensor_group"]:
@@ -232,21 +232,14 @@ def _convert_humming(
232232
weight_scale = weight_scale.repeat_interleave(self.block_structure[0], -2)
233233
group_size = self.block_structure[1]
234234
elif self.strategy == "tensor":
235-
weight_scale = self._may_process_global_scale(
236-
weight_scale,
237-
shape_n_stacks=shape_n_stacks,
238-
shape_k_stacks=shape_k_stacks,
239-
num_experts=num_experts,
240-
force_repeat=True,
241-
).to(param_dtype)
242235
group_size = 0
243236
else:
244237
assert self.strategy == "channel"
245238
group_size = 0
246239

247240
output_tensors = {"weight": weight, "weight_scale": weight_scale}
248241

249-
weight_scale_type = None
242+
weight_scale_type = WeightScaleType.TENSOR if self.strategy == "tensor" else None
250243
weight_scale_2_type = None
251244
if self.format == "nvfp4-pack-quantized":
252245
weight_scale_2 = tensors["weight_global_scale"]
@@ -263,17 +256,20 @@ def _convert_humming(
263256
if has_tensor_scale:
264257
weight_scale_2_type = WeightScale2Type.TENSOR
265258
output_tensors["weight_scale_2"] = weight_scale_2.float()
259+
elif len(shape_n_stacks) > 1:
260+
weight_scale_2_type = WeightScale2Type.CHANNEL
261+
output_tensors["weight_scale_2"] = weight_scale_2.squeeze(-1).to(param_dtype)
266262
else:
267263
weight_scale = weight_scale.float() * weight_scale_2.float()
268264
output_tensors["weight_scale"] = weight_scale.to(param_dtype)
269265

270-
bs_dtype = None
266+
bs_dtype = dtypes.float32 if self.strategy == "tensor" else None
271267
if self.format in ["int-quantized", "float-quantized", "naive-quantized"]:
272268
assert self.num_bits == 8
273269
b_dtype = dtypes.uint8 if self.type == "int" else dtypes.float8e4m3
274270
elif "nvfp4" in self.format:
275271
b_dtype = dtypes.float4e2m1
276-
bs_dtype = dtypes.float8e4m3 if has_tensor_scale else None
272+
bs_dtype = dtypes.float8e4m3 if weight_scale_2_type is not None else None
277273
elif "mxfp4" in self.format:
278274
b_dtype = dtypes.float4e2m1
279275
bs_dtype = dtypes.float8e8m0
@@ -298,6 +294,10 @@ def _convert_humming(
298294
has_zero_point=not self.symmetric,
299295
)
300296

297+
if self.strategy == "tensor":
298+
return schema._convert_humming(
299+
output_tensors, shape_n_stacks, shape_k_stacks, param_dtype, num_experts
300+
)
301301
return schema, output_tensors
302302

303303

‎humming/schema/fp8.py‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,7 @@ def _convert_humming(
105105
weight_scale = tensors[self.weight_scale_key]
106106

107107
if self.weight_block_size is None:
108-
weight_scale = self._may_process_global_scale(
109-
weight_scale,
110-
shape_n_stacks=shape_n_stacks,
111-
shape_k_stacks=shape_k_stacks,
112-
num_experts=num_experts,
113-
force_repeat=True,
114-
).to(param_dtype)
108+
schema = self.to_humming_schema(param_dtype)
115109
else:
116110
shape_n = sum(shape_n_stacks)
117111
scale_block_shape_n = self.weight_block_size[0]
@@ -124,6 +118,10 @@ def _convert_humming(
124118
if "bias" in tensors:
125119
output_tensors["bias"] = tensors["bias"]
126120

121+
if self.weight_block_size is None:
122+
return schema._convert_humming(
123+
output_tensors, shape_n_stacks, shape_k_stacks, param_dtype, num_experts
124+
)
127125
return schema, output_tensors
128126

129127

‎humming/schema/humming.py‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,17 +337,24 @@ def _convert_humming(
337337
shape_n_stacks=shape_n_stacks,
338338
shape_k_stacks=shape_k_stacks,
339339
num_experts=num_experts,
340-
target_group_size=schema.weight_scale_group_size,
340+
target_group_size=schema.weight_scale_group_size if len(shape_k_stacks) > 1 else None,
341341
)
342342

343343
if tensor_scale.nelement() == (num_experts or 1):
344344
tensors[scale_key] = tensor_scale.to(torch.float32)
345345
if is_tensor_only:
346346
schema.bs_dtype = dtypes.float32
347347
elif is_tensor_only:
348-
schema.weight_scale_type = WeightScaleType.CHANNEL
348+
if len(shape_k_stacks) > 1:
349+
schema.weight_scale_type = WeightScaleType.GROUP
350+
schema.weight_scale_group_size = sum(shape_k_stacks) // tensor_scale.size(-1)
351+
else:
352+
schema.weight_scale_type = WeightScaleType.CHANNEL
349353
schema.bs_dtype = dtypes.DataType.from_torch_dtype(param_dtype)
350354
tensors["weight_scale"] = tensor_scale.to(param_dtype)
355+
elif self.weight_scale_type == WeightScaleType.GROUP and len(shape_n_stacks) > 1:
356+
schema.weight_scale_2_type = WeightScale2Type.CHANNEL
357+
tensors["weight_scale_2"] = tensor_scale.squeeze(-1).to(param_dtype)
351358
else:
352359
schema.weight_scale_2_type = WeightScale2Type.NONE
353360
weight_scale = tensors["weight_scale"]

‎humming/schema/modelopt.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ def _convert_humming(
120120
if has_tensor_scale:
121121
weight_scale_2_type = WeightScale2Type.TENSOR
122122
output_tensors["weight_scale_2"] = weight_scale_2.view((num_experts or 1)).float()
123+
elif len(shape_n_stacks) > 1:
124+
weight_scale_2_type = WeightScale2Type.CHANNEL
125+
output_tensors["weight_scale_2"] = weight_scale_2.squeeze(-1).to(param_dtype)
123126
else:
124127
weight_scale_2_type = WeightScale2Type.NONE
125128
weight_scale = weight_scale.float() * weight_scale_2.float()
@@ -130,7 +133,7 @@ def _convert_humming(
130133

131134
schema = HummingWeightSchema(
132135
b_dtype=dtypes.float4e2m1,
133-
bs_dtype=dtypes.float8e4m3 if has_tensor_scale else None,
136+
bs_dtype=dtypes.float8e4m3 if weight_scale_2_type != WeightScale2Type.NONE else None,
134137
weight_scale_group_size=16,
135138
weight_scale_type=WeightScaleType.GROUP,
136139
weight_scale_2_type=weight_scale_2_type,

‎humming/schema/quark.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,13 +450,16 @@ def _convert_humming(
450450
shape_n_stacks,
451451
shape_k_stacks,
452452
num_experts or None,
453-
target_group_size=schema.weight_scale_group_size or None,
453+
target_group_size=schema.weight_scale_group_size if len(shape_k_stacks) > 1 else None,
454454
)
455455
is_group_scale = schema.weight_scale_type == WeightScaleType.GROUP
456456
keep_scale_2 = schema.bs_dtype is not None and is_group_scale
457457
if keep_scale_2 and scale_2.numel() == (num_experts or 1):
458458
schema.weight_scale_2_type = WeightScale2Type.TENSOR
459459
result["weight_scale_2"] = scale_2.reshape(num_experts or 1).float()
460+
elif keep_scale_2 and len(shape_n_stacks) > 1:
461+
schema.weight_scale_2_type = WeightScale2Type.CHANNEL
462+
result["weight_scale_2"] = scale_2.squeeze(-1).to(param_dtype)
460463
else:
461464
if scale_2.numel() == (num_experts or 1):
462465
scale_2 = scale_2.reshape(-1, 1, 1) if num_experts else scale_2.reshape(())

0 commit comments

Comments
 (0)