Skip to content

refactor: remove hardcoded DiT LayerNorm paths#1245

Merged
helloyongyang merged 2 commits into
mainfrom
dev_ln
Jul 18, 2026
Merged

refactor: remove hardcoded DiT LayerNorm paths#1245
helloyongyang merged 2 commits into
mainfrom
dev_ln

Conversation

@Watebear

Copy link
Copy Markdown
Collaborator

No description provided.

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request refactors LayerNorm operations across multiple models (including ErnieImage, Flux2, HunyuanVideo, LongCatImage, Wan, and WorldMirror) to route through registered weight modules instead of calling F.layer_norm directly. It also updates the LayerNorm registry selection to dynamically use the configured layer_norm_type rather than hardcoding "torch", and adds robust handling for LayerNorms without learnable parameters. A new test suite is introduced to enforce these routing rules and lifecycle behaviors. A critical review comment points out that replacing direct F.layer_norm calls in WorldMirror removes dtype-matching logic, which could lead to runtime errors under torch.amp.autocast when mixing float32 weights with float16/bfloat16 activations.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines 118 to +119
def forward(self, x: torch.Tensor) -> torch.Tensor:
w = self.ln_weight._get_actual_weight()
b = self.ln_weight._get_actual_bias()
# Match autocast semantics for a bf16/fp16 activation meeting an
# fp32 LN weight — cast the weight down so the LN runs in the
# activation dtype (what ``nn.LayerNorm`` does under autocast).
if w is not None and x.is_floating_point() and w.dtype != x.dtype and x.dtype in (torch.float16, torch.bfloat16):
w = w.to(x.dtype)
if b is not None:
b = b.to(x.dtype)
return torch.nn.functional.layer_norm(
x,
self.normalized_shape,
w,
b,
self.eps,
)
return self.ln_weight.apply(x)

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.

critical

Replacing the direct F.layer_norm call with self.ln_weight.apply(x) removes the critical dtype-matching logic that was previously present in _LNAdapter.forward.

Under torch.amp.autocast, the activation tensor x is automatically cast to bfloat16 or float16, while the weights stored in self.ln_weight remain in float32. Calling F.layer_norm directly with mixed dtypes (e.g., bfloat16 input and float32 weight) will raise a RuntimeError: expected scalar type BFloat16 but found Float.

To resolve this, the default LNWeight.apply implementation in lightx2v/common/ops/norm/layer_norm_weight.py should be updated to dynamically cast the weight and bias to match the input tensor's dtype, similar to how PyTorch's nn.LayerNorm handles autocast:

def apply(self, input_tensor):
    w = self._get_actual_weight()
    b = self._get_actual_bias()
    if self.sensitive_layer_dtype != self.infer_dtype:
        output_tensor = torch.nn.functional.layer_norm(
            input_tensor.float(),
            (input_tensor.shape[-1],),
            w,
            b,
            self.eps,
        ).to(self.infer_dtype)
    else:
        if w is not None and w.dtype != input_tensor.dtype:
            w = w.to(input_tensor.dtype)
        if b is not None and b.dtype != input_tensor.dtype:
            b = b.to(input_tensor.dtype)
        output_tensor = torch.nn.functional.layer_norm(
            input_tensor,
            (input_tensor.shape[-1],),
            w,
            b,
            self.eps,
        )
    return output_tensor

@helloyongyang
helloyongyang merged commit e91f976 into main Jul 18, 2026
2 checks passed
@helloyongyang
helloyongyang deleted the dev_ln branch July 18, 2026 16:49
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.

2 participants