[Perf] Support TeaCache for MammothModa2 (#5357)
Signed-off-by: nagisa-kun <1434936049@qq.com> Signed-off-by: nagisa <1434936049@qq.com>
This commit is contained in:
1 parent
c9bee166fb
commit
c9c478dd07
12 files changed
+684
-15
No files matched your search
+25
-1
@@ -8,8 +8,9 @@ This module provides the TeaCache backend that implements the CacheBackend
|
||||
interface using the hooks-based TeaCache system.
|
||||
"""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, Protocol
|
||||
|
||||
import torch.nn as nn
|
||||
from vllm.logger import init_logger
|
||||
|
||||
from vllm_omni.diffusion.cache.base import CacheBackend
|
||||
@@ -20,6 +21,11 @@ from vllm_omni.diffusion.data import DiffusionCacheConfig
|
||||
logger = init_logger(__name__)
|
||||
|
||||
|
||||
class _MammothModa2TeaCachePipeline(Protocol):
|
||||
gen_transformer: nn.Module
|
||||
transformer: nn.Module
|
||||
|
||||
|
||||
def enable_hunyuan_image3_teacache(pipeline: Any, config: DiffusionCacheConfig) -> None:
|
||||
"""
|
||||
Enable TeaCache for HunyuanImage3 model.
|
||||
@@ -57,6 +63,23 @@ def enable_bagel_teacache(pipeline: Any, config: DiffusionCacheConfig) -> None:
|
||||
)
|
||||
|
||||
|
||||
def enable_mammoth_moda2_teacache(pipeline: _MammothModa2TeaCachePipeline, config: DiffusionCacheConfig) -> None:
|
||||
"""Enable TeaCache for MammothModa2's DiT stage."""
|
||||
teacache_config = TeaCacheConfig(
|
||||
transformer_type="MammothModa2Transformer2DModel",
|
||||
rel_l1_thresh=config.rel_l1_thresh,
|
||||
coefficients=config.coefficients,
|
||||
)
|
||||
transformer = pipeline.gen_transformer
|
||||
apply_teacache_hook(transformer, teacache_config)
|
||||
pipeline.transformer = transformer
|
||||
|
||||
logger.info(
|
||||
f"TeaCache applied with rel_l1_thresh={teacache_config.rel_l1_thresh}, "
|
||||
f"transformer_class={teacache_config.transformer_type}"
|
||||
)
|
||||
|
||||
|
||||
def enable_sensenova_u1_teacache(pipeline: Any, config: DiffusionCacheConfig) -> None:
|
||||
"""Enable TeaCache for SenseNova-U1 denoising forwards."""
|
||||
teacache_config = TeaCacheConfig(
|
||||
@@ -124,6 +147,7 @@ CUSTOM_TEACACHE_ENABLERS = {
|
||||
"BagelPipeline": enable_bagel_teacache,
|
||||
"Flux2KleinPipeline": enable_flux2_klein_teacache,
|
||||
"HunyuanImage3Pipeline": enable_hunyuan_image3_teacache,
|
||||
"MammothModa2DiTPipeline": enable_mammoth_moda2_teacache,
|
||||
"MiniMaxH3Pipeline": enable_minimax_h3_teacache,
|
||||
"SenseNovaU1Pipeline": enable_sensenova_u1_teacache,
|
||||
}
|
||||
|
||||
+10
@@ -83,6 +83,15 @@ _MODEL_COEFFICIENTS = {
|
||||
],
|
||||
# LongCat Image transformer coefficients
|
||||
"LongCatImageTransformer2DModel": [652.5980, -424.1615, 84.5526, -4.5923, 0.1694],
|
||||
# MammothModa2 DiT coefficients fitted from full-compute traces
|
||||
# at 1024x1024 with 50 denoising steps.
|
||||
"MammothModa2Transformer2DModel": [
|
||||
-1761.242764481119,
|
||||
859.398730831851,
|
||||
-126.78044436937441,
|
||||
9.16173963457422,
|
||||
-0.1102826051200547,
|
||||
],
|
||||
# MiniMax-H3 FL2VA coefficients.
|
||||
"MiniMaxH3DiTModel": [
|
||||
2.283704065852778e03,
|
||||
@@ -95,6 +104,7 @@ _MODEL_COEFFICIENTS = {
|
||||
|
||||
_DEFAULT_REL_L1_THRESH = 0.2
|
||||
_MODEL_DEFAULT_REL_L1_THRESH = {
|
||||
"MammothModa2Transformer2DModel": 0.075,
|
||||
"MiniMaxH3DiTModel": 0.17,
|
||||
}
|
||||
|
||||
|
||||
+110
@@ -20,6 +20,7 @@ from typing import Any
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
from einops import rearrange
|
||||
from vllm.logger import init_logger
|
||||
|
||||
from vllm_omni.diffusion.forward_context import get_forward_context
|
||||
@@ -823,6 +824,114 @@ def extract_longcat_context(
|
||||
)
|
||||
|
||||
|
||||
def extract_mammoth_moda2_context(
|
||||
module: nn.Module,
|
||||
hidden_states: torch.Tensor,
|
||||
timestep: torch.Tensor,
|
||||
text_hidden_states: torch.Tensor,
|
||||
freqs_cis: torch.Tensor,
|
||||
text_attention_mask: torch.Tensor,
|
||||
ref_image_hidden_states: list[list[torch.Tensor]] | None = None,
|
||||
ar_image_hidden_states: torch.Tensor | None = None,
|
||||
ar_image_attention_mask: torch.Tensor | None = None,
|
||||
return_dict: bool = False,
|
||||
teacache_branch: str | None = None,
|
||||
) -> CacheContext:
|
||||
"""Extract cache context for MammothModa2's Lumina-style DiT."""
|
||||
if not hasattr(module, "layers") or len(module.layers) == 0:
|
||||
raise ValueError("Module must have layers")
|
||||
|
||||
batch_size, height, width = module._validate_inputs(
|
||||
hidden_states,
|
||||
text_hidden_states,
|
||||
text_attention_mask,
|
||||
ref_image_hidden_states,
|
||||
return_dict,
|
||||
)
|
||||
|
||||
(
|
||||
temb,
|
||||
text_hidden_states,
|
||||
text_attention_mask,
|
||||
img_tokens,
|
||||
img_mask,
|
||||
img_len,
|
||||
context_rotary_emb,
|
||||
noise_rotary_emb,
|
||||
rotary_emb,
|
||||
encoder_seq_lengths,
|
||||
seq_lengths,
|
||||
) = module._prepare_embeddings(
|
||||
hidden_states,
|
||||
timestep,
|
||||
text_hidden_states,
|
||||
text_attention_mask,
|
||||
freqs_cis,
|
||||
batch_size,
|
||||
height,
|
||||
width,
|
||||
ar_image_hidden_states,
|
||||
ar_image_attention_mask,
|
||||
)
|
||||
|
||||
text_hidden_states, img_tokens = module._apply_refiners(
|
||||
text_hidden_states,
|
||||
text_attention_mask,
|
||||
context_rotary_emb,
|
||||
img_tokens,
|
||||
img_mask,
|
||||
noise_rotary_emb,
|
||||
temb,
|
||||
)
|
||||
|
||||
max_seq_len = max(seq_lengths)
|
||||
attention_mask = img_tokens.new_zeros(batch_size, max_seq_len, dtype=torch.bool)
|
||||
joint_hidden_states = img_tokens.new_zeros(batch_size, max_seq_len, module.config.hidden_size)
|
||||
for i, (encoder_seq_len, seq_len) in enumerate(zip(encoder_seq_lengths, seq_lengths)):
|
||||
attention_mask[i, :seq_len] = True
|
||||
joint_hidden_states[i, :encoder_seq_len] = text_hidden_states[i, :encoder_seq_len]
|
||||
joint_hidden_states[i, encoder_seq_len : encoder_seq_len + img_len] = img_tokens[i, :img_len]
|
||||
|
||||
modulated_input = module.layers[0].norm1(joint_hidden_states, temb)[0]
|
||||
|
||||
def run_transformer_blocks() -> tuple[torch.Tensor]:
|
||||
h = module._apply_transformer_layers(joint_hidden_states, attention_mask, rotary_emb, temb)
|
||||
return (h,)
|
||||
|
||||
def postprocess(h: torch.Tensor) -> torch.Tensor:
|
||||
h = module.norm_out(h, temb)
|
||||
p = module.config.patch_size
|
||||
img_hidden_states = torch.stack(
|
||||
[
|
||||
h[i, encoder_seq_len : encoder_seq_len + img_len]
|
||||
for i, encoder_seq_len in enumerate(encoder_seq_lengths)
|
||||
],
|
||||
dim=0,
|
||||
)
|
||||
return rearrange(
|
||||
img_hidden_states,
|
||||
"b (h w) (p1 p2 c) -> b c (h p1) (w p2)",
|
||||
h=height // p,
|
||||
w=width // p,
|
||||
p1=p,
|
||||
p2=p,
|
||||
)
|
||||
|
||||
extra_states = {}
|
||||
if teacache_branch is not None:
|
||||
extra_states["teacache_branch"] = teacache_branch
|
||||
|
||||
return CacheContext(
|
||||
modulated_input=modulated_input,
|
||||
hidden_states=joint_hidden_states,
|
||||
encoder_hidden_states=None,
|
||||
temb=temb,
|
||||
run_transformer_blocks=run_transformer_blocks,
|
||||
postprocess=postprocess,
|
||||
extra_states=extra_states,
|
||||
)
|
||||
|
||||
|
||||
def extract_stable_audio_context(
|
||||
module: nn.Module,
|
||||
hidden_states: torch.Tensor,
|
||||
@@ -1556,6 +1665,7 @@ EXTRACTOR_REGISTRY: dict[str, Callable] = {
|
||||
"StableAudioDiTModel": extract_stable_audio_context,
|
||||
"Flux2Transformer2DModel": extract_flux2_context,
|
||||
"LongCatImageTransformer2DModel": extract_longcat_context,
|
||||
"MammothModa2Transformer2DModel": extract_mammoth_moda2_context,
|
||||
"FluxTransformer2DModel": extract_flux_context,
|
||||
"SenseNovaU1ForCausalLM": extract_sensenova_u1_context,
|
||||
"MiniMaxH3DiTModel": extract_minimax_h3_context,
|
||||
|
||||
+9
-1
@@ -145,7 +145,15 @@ class TeaCacheHook(ModelHook):
|
||||
# - cfg_rank 0: positive branch
|
||||
# - cfg_rank > 0: negative branch
|
||||
# Without CFG-parallel, branches alternate within a single rank
|
||||
if getattr(module, "do_true_cfg", False):
|
||||
branch_hint = None
|
||||
if getattr(ctx, "extra_states", None):
|
||||
branch_hint = ctx.extra_states.get("teacache_branch")
|
||||
|
||||
if branch_hint is not None:
|
||||
if branch_hint not in ("positive", "negative"):
|
||||
raise ValueError(f"Invalid teacache_branch={branch_hint!r}; expected 'positive' or 'negative'.")
|
||||
cache_branch = branch_hint
|
||||
elif getattr(module, "do_true_cfg", False):
|
||||
cfg_parallel_size = get_classifier_free_guidance_world_size()
|
||||
if cfg_parallel_size > 1:
|
||||
cfg_rank = get_classifier_free_guidance_rank()
|
||||
|
||||
Reference in new issue
Block a user