[NPU] [Diffusion] Performance Optimization for LTX-2 Model (#22445)
Co-authored-by: gengjinsong <gengjinsong@huawei.com> Co-authored-by: gengjinsong <904939979@qq.com> Co-authored-by: ronnie_zheng <zl19940307@163.com>
This commit is contained in:
co-authored by
gengjinsong
gengjinsong
ronnie_zheng
parent
3b417d3999
commit
59eb142ec2
@@ -41,6 +41,9 @@ if _is_cuda or _is_xpu:
|
|||||||
|
|
||||||
if _is_npu:
|
if _is_npu:
|
||||||
import torch_npu
|
import torch_npu
|
||||||
|
from sgl_kernel_npu.norm.rmsnorm_without_weight import (
|
||||||
|
fused_rmsnorm_without_weight,
|
||||||
|
)
|
||||||
|
|
||||||
if _is_musa:
|
if _is_musa:
|
||||||
from sgl_kernel import fused_add_rmsnorm
|
from sgl_kernel import fused_add_rmsnorm
|
||||||
@@ -292,6 +295,18 @@ class RMSNorm(CustomOp):
|
|||||||
return f"hidden_size={self.hidden_size}, eps={self.variance_epsilon}"
|
return f"hidden_size={self.hidden_size}, eps={self.variance_epsilon}"
|
||||||
|
|
||||||
|
|
||||||
|
@CustomOp.register("rms_norm_no_weight")
|
||||||
|
class RMSNormNoWeight(CustomOp):
|
||||||
|
def forward_native(self, x: torch.Tensor, eps: float) -> torch.Tensor:
|
||||||
|
return F.rms_norm(x, normalized_shape=(x.shape[-1],), eps=eps)
|
||||||
|
|
||||||
|
def forward_cuda(self, x: torch.Tensor, eps: float) -> torch.Tensor:
|
||||||
|
return self.forward_native(x, eps=eps)
|
||||||
|
|
||||||
|
def forward_npu(self, x: torch.Tensor, eps: float) -> torch.Tensor:
|
||||||
|
return fused_rmsnorm_without_weight(x, eps)
|
||||||
|
|
||||||
|
|
||||||
# Copied and adapted from sglang
|
# Copied and adapted from sglang
|
||||||
@CustomOp.register("layer_norm")
|
@CustomOp.register("layer_norm")
|
||||||
class LayerNorm(CustomOp):
|
class LayerNorm(CustomOp):
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ from sglang.multimodal_gen.runtime.distributed.communication_op import (
|
|||||||
tensor_model_parallel_all_reduce,
|
tensor_model_parallel_all_reduce,
|
||||||
)
|
)
|
||||||
from sglang.multimodal_gen.runtime.layers.attention import LocalAttention, USPAttention
|
from sglang.multimodal_gen.runtime.layers.attention import LocalAttention, USPAttention
|
||||||
|
from sglang.multimodal_gen.runtime.layers.layernorm import RMSNormNoWeight
|
||||||
from sglang.multimodal_gen.runtime.layers.linear import (
|
from sglang.multimodal_gen.runtime.layers.linear import (
|
||||||
ColumnParallelLinear,
|
ColumnParallelLinear,
|
||||||
RowParallelLinear,
|
RowParallelLinear,
|
||||||
@@ -35,9 +36,14 @@ from sglang.multimodal_gen.runtime.managers.memory_managers.layerwise_offload im
|
|||||||
LayerwiseOffloadableModuleMixin,
|
LayerwiseOffloadableModuleMixin,
|
||||||
)
|
)
|
||||||
from sglang.multimodal_gen.runtime.models.dits.base import CachableDiT
|
from sglang.multimodal_gen.runtime.models.dits.base import CachableDiT
|
||||||
from sglang.multimodal_gen.runtime.platforms import AttentionBackendEnum
|
from sglang.multimodal_gen.runtime.platforms import (
|
||||||
|
AttentionBackendEnum,
|
||||||
|
current_platform,
|
||||||
|
)
|
||||||
from sglang.multimodal_gen.runtime.utils.logging_utils import init_logger
|
from sglang.multimodal_gen.runtime.utils.logging_utils import init_logger
|
||||||
|
|
||||||
|
_is_npu = current_platform.is_npu()
|
||||||
|
|
||||||
logger = init_logger(__name__)
|
logger = init_logger(__name__)
|
||||||
|
|
||||||
ADALN_NUM_BASE_PARAMS = 6
|
ADALN_NUM_BASE_PARAMS = 6
|
||||||
@@ -393,10 +399,6 @@ class LTX2AudioVideoRotaryPosEmbed(nn.Module):
|
|||||||
return cos_freqs.to(dtype=out_dtype), sin_freqs.to(dtype=out_dtype)
|
return cos_freqs.to(dtype=out_dtype), sin_freqs.to(dtype=out_dtype)
|
||||||
|
|
||||||
|
|
||||||
def rms_norm(x: torch.Tensor, eps: float) -> torch.Tensor:
|
|
||||||
return F.rms_norm(x, normalized_shape=(x.shape[-1],), eps=eps)
|
|
||||||
|
|
||||||
|
|
||||||
class LTX2TextProjection(nn.Module):
|
class LTX2TextProjection(nn.Module):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -839,6 +841,7 @@ class LTX2TransformerBlock(nn.Module):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.idx = idx
|
self.idx = idx
|
||||||
self.norm_eps = norm_eps
|
self.norm_eps = norm_eps
|
||||||
|
self.rms_norm = RMSNormNoWeight()
|
||||||
# LTX2.3
|
# LTX2.3
|
||||||
self.cross_attention_adaln = cross_attention_adaln
|
self.cross_attention_adaln = cross_attention_adaln
|
||||||
self.use_local_av_cross_attention = use_local_av_cross_attention
|
self.use_local_av_cross_attention = use_local_av_cross_attention
|
||||||
@@ -1015,7 +1018,7 @@ class LTX2TransformerBlock(nn.Module):
|
|||||||
self.scale_shift_table, batch_size, temb, slice(0, 3)
|
self.scale_shift_table, batch_size, temb, slice(0, 3)
|
||||||
)
|
)
|
||||||
norm_hidden_states = (
|
norm_hidden_states = (
|
||||||
rms_norm(hidden_states, self.norm_eps) * (1 + vscale_msa) + vshift_msa
|
self.rms_norm(hidden_states, self.norm_eps) * (1 + vscale_msa) + vshift_msa
|
||||||
)
|
)
|
||||||
attn_hidden_states = self.attn1(
|
attn_hidden_states = self.attn1(
|
||||||
norm_hidden_states,
|
norm_hidden_states,
|
||||||
@@ -1031,7 +1034,8 @@ class LTX2TransformerBlock(nn.Module):
|
|||||||
self.audio_scale_shift_table, batch_size, temb_audio, slice(0, 3)
|
self.audio_scale_shift_table, batch_size, temb_audio, slice(0, 3)
|
||||||
)
|
)
|
||||||
norm_audio_hidden_states = (
|
norm_audio_hidden_states = (
|
||||||
rms_norm(audio_hidden_states, self.norm_eps) * (1 + ascale_msa) + ashift_msa
|
self.rms_norm(audio_hidden_states, self.norm_eps) * (1 + ascale_msa)
|
||||||
|
+ ashift_msa
|
||||||
)
|
)
|
||||||
attn_audio_hidden_states = self.audio_attn1(
|
attn_audio_hidden_states = self.audio_attn1(
|
||||||
norm_audio_hidden_states,
|
norm_audio_hidden_states,
|
||||||
@@ -1056,7 +1060,7 @@ class LTX2TransformerBlock(nn.Module):
|
|||||||
self.prompt_scale_shift_table, batch_size, temb_prompt, slice(None)
|
self.prompt_scale_shift_table, batch_size, temb_prompt, slice(None)
|
||||||
)
|
)
|
||||||
norm_hidden_states = (
|
norm_hidden_states = (
|
||||||
rms_norm(hidden_states, self.norm_eps) * (1 + vscale_q) + vshift_q
|
self.rms_norm(hidden_states, self.norm_eps) * (1 + vscale_q) + vshift_q
|
||||||
)
|
)
|
||||||
mod_encoder_hidden_states = (
|
mod_encoder_hidden_states = (
|
||||||
encoder_hidden_states * (1 + v_prompt_scale) + v_prompt_shift
|
encoder_hidden_states * (1 + v_prompt_scale) + v_prompt_shift
|
||||||
@@ -1078,7 +1082,8 @@ class LTX2TransformerBlock(nn.Module):
|
|||||||
slice(None),
|
slice(None),
|
||||||
)
|
)
|
||||||
norm_audio_hidden_states = (
|
norm_audio_hidden_states = (
|
||||||
rms_norm(audio_hidden_states, self.norm_eps) * (1 + ascale_q) + ashift_q
|
self.rms_norm(audio_hidden_states, self.norm_eps) * (1 + ascale_q)
|
||||||
|
+ ashift_q
|
||||||
)
|
)
|
||||||
mod_audio_encoder_hidden_states = (
|
mod_audio_encoder_hidden_states = (
|
||||||
audio_encoder_hidden_states * (1 + a_prompt_scale) + a_prompt_shift
|
audio_encoder_hidden_states * (1 + a_prompt_scale) + a_prompt_shift
|
||||||
@@ -1092,7 +1097,7 @@ class LTX2TransformerBlock(nn.Module):
|
|||||||
audio_hidden_states + attn_audio_hidden_states * agate_q
|
audio_hidden_states + attn_audio_hidden_states * agate_q
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
norm_hidden_states = rms_norm(hidden_states, self.norm_eps)
|
norm_hidden_states = self.rms_norm(hidden_states, self.norm_eps)
|
||||||
attn_hidden_states = self.attn2(
|
attn_hidden_states = self.attn2(
|
||||||
norm_hidden_states,
|
norm_hidden_states,
|
||||||
context=encoder_hidden_states,
|
context=encoder_hidden_states,
|
||||||
@@ -1100,7 +1105,7 @@ class LTX2TransformerBlock(nn.Module):
|
|||||||
)
|
)
|
||||||
hidden_states = hidden_states + attn_hidden_states
|
hidden_states = hidden_states + attn_hidden_states
|
||||||
|
|
||||||
norm_audio_hidden_states = rms_norm(audio_hidden_states, self.norm_eps)
|
norm_audio_hidden_states = self.rms_norm(audio_hidden_states, self.norm_eps)
|
||||||
attn_audio_hidden_states = self.audio_attn2(
|
attn_audio_hidden_states = self.audio_attn2(
|
||||||
norm_audio_hidden_states,
|
norm_audio_hidden_states,
|
||||||
context=audio_encoder_hidden_states,
|
context=audio_encoder_hidden_states,
|
||||||
@@ -1108,8 +1113,8 @@ class LTX2TransformerBlock(nn.Module):
|
|||||||
)
|
)
|
||||||
audio_hidden_states = audio_hidden_states + attn_audio_hidden_states
|
audio_hidden_states = audio_hidden_states + attn_audio_hidden_states
|
||||||
# 3. Audio-to-Video and Video-to-Audio Cross-Attention
|
# 3. Audio-to-Video and Video-to-Audio Cross-Attention
|
||||||
norm_hidden_states = rms_norm(hidden_states, self.norm_eps)
|
norm_hidden_states = self.rms_norm(hidden_states, self.norm_eps)
|
||||||
norm_audio_hidden_states = rms_norm(audio_hidden_states, self.norm_eps)
|
norm_audio_hidden_states = self.rms_norm(audio_hidden_states, self.norm_eps)
|
||||||
|
|
||||||
# Compute combined ada params
|
# Compute combined ada params
|
||||||
video_per_layer_ca_scale_shift = self.video_a2v_cross_attn_scale_shift_table[
|
video_per_layer_ca_scale_shift = self.video_a2v_cross_attn_scale_shift_table[
|
||||||
@@ -1221,7 +1226,7 @@ class LTX2TransformerBlock(nn.Module):
|
|||||||
self.scale_shift_table, batch_size, temb, slice(3, 6)
|
self.scale_shift_table, batch_size, temb, slice(3, 6)
|
||||||
)
|
)
|
||||||
norm_hidden_states = (
|
norm_hidden_states = (
|
||||||
rms_norm(hidden_states, self.norm_eps) * (1 + vscale_mlp) + vshift_mlp
|
self.rms_norm(hidden_states, self.norm_eps) * (1 + vscale_mlp) + vshift_mlp
|
||||||
)
|
)
|
||||||
ff_output = self.ff(norm_hidden_states)
|
ff_output = self.ff(norm_hidden_states)
|
||||||
hidden_states = hidden_states + ff_output * vgate_mlp
|
hidden_states = hidden_states + ff_output * vgate_mlp
|
||||||
@@ -1230,7 +1235,8 @@ class LTX2TransformerBlock(nn.Module):
|
|||||||
self.audio_scale_shift_table, batch_size, temb_audio, slice(3, 6)
|
self.audio_scale_shift_table, batch_size, temb_audio, slice(3, 6)
|
||||||
)
|
)
|
||||||
norm_audio_hidden_states = (
|
norm_audio_hidden_states = (
|
||||||
rms_norm(audio_hidden_states, self.norm_eps) * (1 + ascale_mlp) + ashift_mlp
|
self.rms_norm(audio_hidden_states, self.norm_eps) * (1 + ascale_mlp)
|
||||||
|
+ ashift_mlp
|
||||||
)
|
)
|
||||||
audio_ff_output = self.audio_ff(norm_audio_hidden_states)
|
audio_ff_output = self.audio_ff(norm_audio_hidden_states)
|
||||||
audio_hidden_states = audio_hidden_states + audio_ff_output * agate_mlp
|
audio_hidden_states = audio_hidden_states + audio_ff_output * agate_mlp
|
||||||
@@ -1813,6 +1819,17 @@ class LTX2VideoTransformer3DModel(CachableDiT, LayerwiseOffloadableModuleMixin):
|
|||||||
audio_encoder_hidden_states = self.audio_caption_projection(
|
audio_encoder_hidden_states = self.audio_caption_projection(
|
||||||
audio_encoder_hidden_states
|
audio_encoder_hidden_states
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if _is_npu:
|
||||||
|
# If the 'encoder_attention_mask' is provided and it is all ones,
|
||||||
|
# it can be set to 'None' to avoid the degradation of performance on the NPU side,
|
||||||
|
# where the mask, even though it has no affect,
|
||||||
|
# can lead to the introduction of multiple small operators.
|
||||||
|
if encoder_attention_mask is not None and torch.all(
|
||||||
|
encoder_attention_mask == 1
|
||||||
|
):
|
||||||
|
encoder_attention_mask = None
|
||||||
|
|
||||||
# 5. Run blocks
|
# 5. Run blocks
|
||||||
skip_video_self_attn_blocks = set(skip_video_self_attn_blocks or ())
|
skip_video_self_attn_blocks = set(skip_video_self_attn_blocks or ())
|
||||||
skip_audio_self_attn_blocks = set(skip_audio_self_attn_blocks or ())
|
skip_audio_self_attn_blocks = set(skip_audio_self_attn_blocks or ())
|
||||||
|
|||||||
Reference in New Issue
Block a user