Add HPU FP8 Linear GEMM support for Wan transformer blocks#23
Open
Wei-Lin-Intel with Copilot wants to merge 16 commits into
Open
Add HPU FP8 Linear GEMM support for Wan transformer blocks#23Wei-Lin-Intel with Copilot wants to merge 16 commits into
Wei-Lin-Intel with Copilot wants to merge 16 commits into
Conversation
- Add wan/utils/fp8_linear.py with WanFP8Linear, dynamic_quant, apply_fp8_linear_hpu, and wrap_blocks_linear_fp8 utilities - Add --fp8 CLI flag to generate.py - Update WanI2V, WanT2V, WanTI2V, WanS2V __init__ and _configure_model to accept fp8 parameter and wrap blocks Linear layers at init time Agent-Logs-Url: https://github.com/wenbinc-Bin/Wan2.2/sessions/eadb65ce-e852-465b-a87e-f8dc391a1df7 Co-authored-by: Wei-Lin-Intel <63534993+Wei-Lin-Intel@users.noreply.github.com>
Agent-Logs-Url: https://github.com/wenbinc-Bin/Wan2.2/sessions/eadb65ce-e852-465b-a87e-f8dc391a1df7 Co-authored-by: Wei-Lin-Intel <63534993+Wei-Lin-Intel@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Add support for HPU FP8 Linear GEMM in Wan models
Add HPU FP8 Linear GEMM support for Wan transformer blocks
May 12, 2026
Wei-Lin-Intel
marked this pull request as ready for review
May 14, 2026 06:57
mengker33
reviewed
May 14, 2026
| @@ -277,8 +309,30 @@ def forward(self, x, context, context_lens): | |||
|
|
|||
| # compute query, key, value | |||
| q = self.norm_q(self.q(x)).reshape(b, -1, n, d) | |||
Collaborator
Collaborator
There was a problem hiding this comment.
There is fp8 for q in cross-attn because cross-attn is in transformer blocks. But in cross-attn, q Linear uses x as the input, and k/v Linears use context as the input, so the dequant of context can be shared for k/v, unlike q/k/v shares the same input tensor in self-attn.
All the Linears in transformer blocks has been wrapped by WanFP8Linear. Its forward function would perform dequant for input tensor. Since some Linears share the input in self/cross-attn, I seperate the dequant OP for them.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Adds
--fp8flag to Wan inference pipelines (i2v, t2v, ti2v, s2v) that quantises allnn.Linearlayers insidemodel.blocksto per-output-channel FP8 at init time, freeing BF16 weights immediately. Forward pass uses dynamic per-row activation quantisation and HPUfp8_gemm_v2. All other Linear layers (embeddings, heads, etc.) remain BF16.New:
wan/utils/fp8_linear.pyWanFP8Linear—nn.Modulewrapper fornn.Linear; precomputesweight_fp8([out, in],float8_e4m3fn) andweight_scale([out, 1],float32) as buffers, deletes original BF16 weight at initapply_fp8_linear_hpu— HPU FP8 GEMM viatorch.ops.hpu.fp8_gemm_v2with dynamic per-row activation quant (dynamic_quant)wrap_blocks_linear_fp8(model)— replaces everynn.Linearinmodel.blocksin-place; no-ops on anything outside blocksPipeline changes (
WanI2V,WanT2V,WanTI2V,WanS2V)__init__and_configure_modelacceptfp8=False; when enabled,wrap_blocks_linear_fp8runs before device placement so buffers are moved to HPU alongside the rest of the modelCLI (
generate.py)--fp8flag wired through to all four pipeline constructors# Example: enable FP8 for i2v inference python generate.py --task i2v-A14B --fp8 --ckpt_dir /path/to/ckpt ...Constraint: weight compression is strictly a one-time init-time operation —
forwardonly quantises activations dynamically.Original prompt
In repository
wenbinc-Bin/Wan2.2, create a pull request targeting branchhputo add HPU FP8 Linear GEMM support for Wan inference models.Requirements:
--fp8.--fp8is enabled during model initialization, convert eligible Linear layers into an FP8-wrapped implementation at initialization time.self.blocksfor:WanModelWanModel_S2Vapply_fp8_linear_hpu(...)helper and dynamic quantization path for activations._configure_modelif appropriate.torch.nn.Linear--fp8is not provided.Relevant context from user:
wan/textimage2video.pyon branchhpuapply_fp8_linear_hpu(input, weight, weight_scale, input_scale=None, bias=None, trans_B=True)dynamic_quant(data, single_scale=False)Deliverables:
hpuhpuThe following is the prior conversation context from the user's chat exploration (may be truncated):
User: ```
class AutoWrappedLinear(torch.nn.Linear, AutoTorchModule):
def init(
self,
module: torch.nn.Linear,
offload_dtype: torch.dtype = None,
offload_device: Union[str, torch.device] = None,
onload_dtype: torch.dtype = None,
onload_device: Union[str, torch.device] = None,
preparing_dtype: torch.dtype = None,
preparing_device: Union[str, torch.device] = None,
computation_dtype: torch.dtype = None,
computation_device: Union[str, torch.device] = None,
vram_limit: float = None,
name: str = "",
disk_map: DiskMap = None,
**kwargs
):
with skip_model_initialization():
super().init(
in_features=module.in_features,
out_features=module.out_features,
bias=module.bias is not None,
)
self.set_dtype_and_device(
offload_dtype,
offload_device,
onload_dtype,
onload_device,
preparing_dtype,
preparing_device,
computation_dtype,
computation_device,
vram_limit,
)
self.weight = module.weight
self.bias = module.bias
self.state = 0
self.name = name
self.lora_A_weights = []
self.lora_B_weights = []
self.lora_merger = None
...
This pull request was created from Copilot chat.