feat(diffusion): add regional torch compile (#32696)
This commit is contained in:
@@ -406,11 +406,22 @@ class DenoisingStage(PipelineStage, RolloutDenoisingMixin):
|
|||||||
compile_kwargs = build_torch_compile_kwargs(mode=mode)
|
compile_kwargs = build_torch_compile_kwargs(mode=mode)
|
||||||
logger.info(f"Compiling transformer with mode: {mode}")
|
logger.info(f"Compiling transformer with mode: {mode}")
|
||||||
|
|
||||||
# TODO(triple-mu): support customized fullgraph and dynamic in the future
|
if getattr(self.server_args, "regional_compile", False):
|
||||||
self._torch_compile_registry.compile_once(
|
compiled_count = self._torch_compile_registry.compile_regions_once(
|
||||||
module,
|
module,
|
||||||
compile_kwargs=compile_kwargs,
|
compile_kwargs=compile_kwargs,
|
||||||
)
|
)
|
||||||
|
logger.info(
|
||||||
|
"Enabled regional torch.compile for %d submodules in %s",
|
||||||
|
compiled_count,
|
||||||
|
type(module).__name__,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# TODO(triple-mu): support customized fullgraph and dynamic in the future
|
||||||
|
self._torch_compile_registry.compile_once(
|
||||||
|
module,
|
||||||
|
compile_kwargs=compile_kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
def _maybe_enable_cache_dit_and_torch_compile(
|
def _maybe_enable_cache_dit_and_torch_compile(
|
||||||
self, num_inference_steps: int | tuple[int, int], batch: Req
|
self, num_inference_steps: int | tuple[int, int], batch: Req
|
||||||
|
|||||||
@@ -284,6 +284,7 @@ class ServerArgs(DisaggServerArgsMixin):
|
|||||||
|
|
||||||
# Compilation
|
# Compilation
|
||||||
enable_torch_compile: bool = False
|
enable_torch_compile: bool = False
|
||||||
|
regional_compile: bool = False
|
||||||
|
|
||||||
# Breakable CUDA graph (BCG): capture the DiT forward as CUDA-graph
|
# Breakable CUDA graph (BCG): capture the DiT forward as CUDA-graph
|
||||||
# segments split at attention modules (SP all-to-all / dynamic attention
|
# segments split at attention modules (SP all-to-all / dynamic attention
|
||||||
@@ -1513,6 +1514,16 @@ class ServerArgs(DisaggServerArgsMixin):
|
|||||||
+ "so first real requests do not pay compile latency. "
|
+ "so first real requests do not pay compile latency. "
|
||||||
+ "However, will likely cause precision drifts. See (https://github.com/pytorch/pytorch/issues/145213)",
|
+ "However, will likely cause precision drifts. See (https://github.com/pytorch/pytorch/issues/145213)",
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--regional-compile",
|
||||||
|
action=StoreBoolean,
|
||||||
|
default=ServerArgs.regional_compile,
|
||||||
|
help=(
|
||||||
|
"Compile repeated DiT submodules selected by the model's "
|
||||||
|
"_compile_conditions instead of compiling the whole transformer. "
|
||||||
|
"Requires --enable-torch-compile."
|
||||||
|
),
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--offload-during-compile",
|
"--offload-during-compile",
|
||||||
action=StoreBoolean,
|
action=StoreBoolean,
|
||||||
|
|||||||
@@ -45,6 +45,28 @@ def resolve_torch_compile_mode(
|
|||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
|
def compile_matching_submodules(
|
||||||
|
module: nn.Module,
|
||||||
|
*,
|
||||||
|
compile_kwargs: dict[str, object],
|
||||||
|
) -> int:
|
||||||
|
conditions = getattr(module, "_compile_conditions", ())
|
||||||
|
matches = [
|
||||||
|
submodule
|
||||||
|
for name, submodule in module.named_modules()
|
||||||
|
if name and any(condition(name, submodule) for condition in conditions)
|
||||||
|
]
|
||||||
|
if not matches:
|
||||||
|
raise ValueError(
|
||||||
|
"regional compile found no matching submodules; "
|
||||||
|
f"check {type(module).__name__}._compile_conditions"
|
||||||
|
)
|
||||||
|
|
||||||
|
for submodule in matches:
|
||||||
|
submodule.compile(**compile_kwargs)
|
||||||
|
return len(matches)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class CompiledModuleRegistry:
|
class CompiledModuleRegistry:
|
||||||
module_ids: set[int] = field(default_factory=set)
|
module_ids: set[int] = field(default_factory=set)
|
||||||
@@ -65,6 +87,22 @@ class CompiledModuleRegistry:
|
|||||||
self.module_ids.add(module_id)
|
self.module_ids.add(module_id)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def compile_regions_once(
|
||||||
|
self,
|
||||||
|
module: nn.Module,
|
||||||
|
*,
|
||||||
|
compile_kwargs: dict[str, object],
|
||||||
|
) -> int:
|
||||||
|
module_id = id(module)
|
||||||
|
if module_id in self.module_ids:
|
||||||
|
return 0
|
||||||
|
compiled_count = compile_matching_submodules(
|
||||||
|
module,
|
||||||
|
compile_kwargs=compile_kwargs,
|
||||||
|
)
|
||||||
|
self.module_ids.add(module_id)
|
||||||
|
return compiled_count
|
||||||
|
|
||||||
|
|
||||||
class CallableModule(nn.Module):
|
class CallableModule(nn.Module):
|
||||||
"""Module wrapper for compiling non-forward callables with module.compile"""
|
"""Module wrapper for compiling non-forward callables with module.compile"""
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
from types import SimpleNamespace
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import torch.nn as nn
|
||||||
|
|
||||||
|
from sglang.multimodal_gen.configs.models.dits.ltx_2 import LTX2ArchConfig
|
||||||
|
from sglang.multimodal_gen.runtime.pipelines_core.stages.denoising import (
|
||||||
|
DenoisingStage,
|
||||||
|
)
|
||||||
|
from sglang.multimodal_gen.runtime.utils.torch_compile import (
|
||||||
|
CompiledModuleRegistry,
|
||||||
|
compile_matching_submodules,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class _CompilableModule(nn.Module):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.compile_calls = []
|
||||||
|
|
||||||
|
def compile(self, **kwargs):
|
||||||
|
self.compile_calls.append(kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class _RegionalModel(_CompilableModule):
|
||||||
|
_compile_conditions = [
|
||||||
|
lambda name, _module: name.startswith("transformer_blocks.")
|
||||||
|
and name.count(".") == 1
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.transformer_blocks = nn.ModuleList(
|
||||||
|
[_CompilableModule(), _CompilableModule()]
|
||||||
|
)
|
||||||
|
self.transformer_blocks[0].inner = _CompilableModule()
|
||||||
|
self.proj_out = _CompilableModule()
|
||||||
|
|
||||||
|
|
||||||
|
def test_ltx2_compile_conditions_match_only_direct_blocks():
|
||||||
|
conditions = LTX2ArchConfig()._compile_conditions
|
||||||
|
|
||||||
|
assert conditions
|
||||||
|
assert any(condition("transformer_blocks.0", object()) for condition in conditions)
|
||||||
|
assert not any(
|
||||||
|
condition("transformer_blocks.0.attn1", object()) for condition in conditions
|
||||||
|
)
|
||||||
|
assert not any(
|
||||||
|
condition("transformer_blocks", object()) for condition in conditions
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_compile_matching_submodules_matches_only_declared_regions():
|
||||||
|
model = _RegionalModel()
|
||||||
|
|
||||||
|
count = compile_matching_submodules(
|
||||||
|
model,
|
||||||
|
compile_kwargs={"mode": "default", "fullgraph": False},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert count == 2
|
||||||
|
assert [len(block.compile_calls) for block in model.transformer_blocks] == [1, 1]
|
||||||
|
assert not model.transformer_blocks[0].inner.compile_calls
|
||||||
|
assert not model.proj_out.compile_calls
|
||||||
|
assert not model.compile_calls
|
||||||
|
|
||||||
|
|
||||||
|
def test_compile_matching_submodules_fails_when_no_region_matches():
|
||||||
|
model = _RegionalModel()
|
||||||
|
model._compile_conditions = [lambda _name, _module: False]
|
||||||
|
|
||||||
|
with pytest.raises(ValueError, match="no matching submodules"):
|
||||||
|
compile_matching_submodules(model, compile_kwargs={"mode": "default"})
|
||||||
|
|
||||||
|
|
||||||
|
def test_compiled_module_registry_installs_regions_once():
|
||||||
|
model = _RegionalModel()
|
||||||
|
registry = CompiledModuleRegistry()
|
||||||
|
|
||||||
|
assert (
|
||||||
|
registry.compile_regions_once(
|
||||||
|
model,
|
||||||
|
compile_kwargs={"mode": "default"},
|
||||||
|
)
|
||||||
|
== 2
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
registry.compile_regions_once(
|
||||||
|
model,
|
||||||
|
compile_kwargs={"mode": "default"},
|
||||||
|
)
|
||||||
|
== 0
|
||||||
|
)
|
||||||
|
assert [len(block.compile_calls) for block in model.transformer_blocks] == [1, 1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_denoising_stage_selects_regional_compile():
|
||||||
|
model = _RegionalModel()
|
||||||
|
stage = DenoisingStage.__new__(DenoisingStage)
|
||||||
|
stage.server_args = SimpleNamespace(
|
||||||
|
enable_breakable_cuda_graph=False,
|
||||||
|
enable_torch_compile=True,
|
||||||
|
regional_compile=True,
|
||||||
|
pipeline_config=SimpleNamespace(
|
||||||
|
dit_config=SimpleNamespace(torch_compile_mode="default")
|
||||||
|
),
|
||||||
|
)
|
||||||
|
stage._cache_dit_enabled = False
|
||||||
|
stage._torch_compile_registry = CompiledModuleRegistry()
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"sglang.multimodal_gen.runtime.pipelines_core.stages.denoising."
|
||||||
|
"current_platform.is_npu",
|
||||||
|
return_value=False,
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"sglang.multimodal_gen.runtime.pipelines_core.stages.denoising."
|
||||||
|
"maybe_enable_inductor_compute_comm_overlap"
|
||||||
|
),
|
||||||
|
):
|
||||||
|
stage._maybe_torch_compile(model)
|
||||||
|
|
||||||
|
assert [len(block.compile_calls) for block in model.transformer_blocks] == [1, 1]
|
||||||
|
assert not model.compile_calls
|
||||||
Reference in New Issue
Block a user