Skip to content

fix unit_moe: use loaded weight scales, force activation scale=1.0 - #1456

Draft
yangulei wants to merge 2 commits into
vllm-project:aicefrom
yangulei:unit_moe
Draft

fix unit_moe: use loaded weight scales, force activation scale=1.0#1456
yangulei wants to merge 2 commits into
vllm-project:aicefrom
yangulei:unit_moe

Conversation

@yangulei

Copy link
Copy Markdown
Collaborator

The previous unit_moe implementation forced both weight and activation scales to 1.0, which caused accuracy issues in some cases.

This fix changes the behavior to:

  • Use the loaded scales for weights (no longer force to 1.0)
  • Force scale=1.0 only for activation (both dynamic and static paths)

Changes:

  • Removed the weight rescaling block in fp8_channel_moe_prepare_weights that was absorbing scales into weights
  • In VllmMixtureOfExpertsOpFP8PerChannel.forward: weight scales always use loaded values; only activation scales (x_scale, w2_input_scale) are forced to 1.0 when enable_unit_moe is set

The previous implementation forced both weight and activation scales to 1.0,
which caused accuracy issues. Now only activation scales are forced to 1.0
while weight scales use the loaded values from the model.

Signed-off-by: Youlei Yang <youlei.yang@intel.com>
Copilot AI review requested due to automatic review settings May 19, 2026 06:45
@yangulei
yangulei marked this pull request as draft May 19, 2026 06:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes enable_unit_moe behavior for FP8 per-channel MoE on Gaudi by preserving loaded weight scales (to avoid accuracy regressions) while still forcing activation scales to 1.0 in unit-moe mode.

Changes:

  • Removed the unit-moe weight “scale absorption” logic from fp8_channel_moe_prepare_weights so weights are no longer rescaled to implicitly bake in scales.
  • Updated VllmMixtureOfExpertsOpFP8PerChannel.forward so weight scales always use loaded values, while unit-moe forces activation quantization scale (x_scale) to 1.0 in the dynamic path.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1227 to +1231
if self.enable_unit_moe:
x_fp8 = torch.ops.hpu.cast_to_fp8_v2(x, 1.0, False, False, torch.float8_e4m3fn)[0]
x_scale = 1.0
else:
x_fp8, x_scale = dynamic_quant(x)
@czhu15

czhu15 commented May 19, 2026

Copy link
Copy Markdown
Collaborator

will this change impacts the runtime performance?

@yangulei

Copy link
Copy Markdown
Collaborator Author

will this change impacts the runtime performance?

Not sure.
This PR is for the accuracy issue of AA_LCR benchmark reported by Yinghao. He will check the performance and accuracy of this change. I will change it to 'Ready for review' if the performance and accuracy both ok.

Move .item() conversion of weight scales to fp8_channel_moe_prepare_weights
(called once at weight load time) to avoid H2D transfers during inference.
The pre-computed scalar lists are stored on moe_op and used directly in forward.

Signed-off-by: Youlei Yang <youlei.yang@intel.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants