Skip to content

Commit b7226d8

Browse files
committed
remove compile dict
1 parent d20f4be commit b7226d8

3 files changed

Lines changed: 41 additions & 46 deletions

File tree

fastgen/configs/config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ class BaseModelConfig:
160160
# - however, it is required if the model has a discriminator or the net initializes unused modules (e.g., for logvar predictions)
161161
ddp_find_unused_parameters: bool = True
162162

163-
# torch.compile mode for the networks in `compile_dict` ("default", "reduce-overhead", "max-autotune")
164-
# None disables torch.compile.
163+
# torch.compile mode for the training networks ("default", "reduce-overhead", "max-autotune")
164+
# applied in apply_torch_compile. None disables torch.compile.
165165
torch_compile_mode: Optional[str] = None
166166

167167
# precision variables (choose from "float64", "float32", "bfloat16", or "float16")

fastgen/methods/model.py

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
class FastGenModel(torch.nn.Module):
2727
# Preprocessor sub-objects of ``net`` (handled specially for device/dtype placement
28-
# in on_train_begin and for torch.compile in compile_dict). Single source of truth.
28+
# in on_train_begin and for torch.compile in apply_torch_compile). Single source of truth.
2929
_PREPROCESSOR_ATTRS = ("vae", "text_encoder", "image_encoder")
3030

3131
def __init__(self, config: BaseModelConfig):
@@ -268,22 +268,28 @@ def build_model(self):
268268
if hasattr(self.net, "init_preprocessors") and self.config.enable_preprocessors:
269269
self.net.init_preprocessors()
270270

271-
@property
272-
def compile_dict(self) -> dict:
273-
"""Return dict of modules to compile with torch.compile, keyed by name.
274-
275-
Built from model_dict (e.g. net, plus fake_score/discriminator for DMD2)
276-
minus the EMA networks, plus the teacher (if any, cf. fsdp_dict) and the
277-
net's preprocessors. Compilation is applied in place (via
278-
``nn.Module.compile``) by ``apply_torch_compile``, which the trainer calls
279-
*after* DDP/FSDP wrapping so torch.compile composes with the wrappers.
271+
def apply_torch_compile(self):
272+
"""Compile the training networks in place with torch.compile.
273+
274+
Called by the trainer after DDP/FSDP wrapping (and after the networks
275+
have been moved to their device in ``on_train_begin``) so torch.compile
276+
composes with the distributed wrappers. No-op when
277+
``config.torch_compile_mode`` is None.
278+
279+
The modules compiled are those in model_dict (e.g. net, plus
280+
fake_score/discriminator for DMD2) minus the EMA networks, plus the
281+
teacher (if any, cf. fsdp_dict) and the net's preprocessors.
280282
"""
283+
mode = self.config.torch_compile_mode
284+
if mode is None:
285+
return
286+
281287
# model_dict contains the trainable networks (incl. EMA); EMA networks are
282288
# weight-averaged copies that aren't run during training, so drop them.
283-
compile_dict = {name: net for name, net in self.model_dict.items() if name not in self.ema_dict}
289+
modules = {name: net for name, net in self.model_dict.items() if name not in self.ema_dict}
284290
# The teacher is not part of model_dict; add it when present (cf. fsdp_dict).
285291
if getattr(self, "teacher", None) is not None:
286-
compile_dict["teacher"] = self.teacher
292+
modules["teacher"] = self.teacher
287293
# Preprocessors (VAE, text/image encoders) are often lightweight wrappers
288294
# (e.g. WanVideoEncoder, SDVAE) that are not nn.Modules themselves but hold
289295
# the actual nn.Module under an attribute; compile those submodules too.
@@ -292,24 +298,13 @@ def compile_dict(self) -> dict:
292298
if obj is None:
293299
continue
294300
if isinstance(obj, torch.nn.Module):
295-
compile_dict[name] = obj
301+
modules[name] = obj
296302
else:
297303
for attr, submodule in getattr(obj, "__dict__", {}).items():
298304
if isinstance(submodule, torch.nn.Module):
299-
compile_dict[f"{name}.{attr}"] = submodule
300-
return compile_dict
301-
302-
def apply_torch_compile(self):
303-
"""Compile the modules in ``compile_dict`` in place with torch.compile.
305+
modules[f"{name}.{attr}"] = submodule
304306

305-
Called by the trainer after DDP/FSDP wrapping (and after the networks
306-
have been moved to their device in ``on_train_begin``). No-op when
307-
``config.torch_compile_mode`` is None.
308-
"""
309-
mode = self.config.torch_compile_mode
310-
if mode is None:
311-
return
312-
for name, module in self.compile_dict.items():
307+
for name, module in modules.items():
313308
logger.info(f"Applying torch.compile (mode={mode}) to {name}")
314309
module.compile(mode=mode)
315310

tests/test_torch_compile.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,11 @@ def test_sft_compile_disabled(sft_model_not_compiled):
110110

111111

112112
def test_dmd2_compile_enabled(dmd2_model_compiled):
113+
# apply_torch_compile draws from model_dict (net, fake_score, discriminator) plus the teacher.
113114
assert _is_compiled(dmd2_model_compiled.net)
114115
assert _is_compiled(dmd2_model_compiled.teacher)
115116
assert _is_compiled(dmd2_model_compiled.fake_score)
117+
assert _is_compiled(dmd2_model_compiled.discriminator)
116118

117119

118120
def test_dmd2_compile_disabled(dmd2_model_not_compiled):
@@ -121,26 +123,24 @@ def test_dmd2_compile_disabled(dmd2_model_not_compiled):
121123
assert not _is_compiled(dmd2_model_not_compiled.fake_score)
122124

123125

124-
def test_compile_dict_contains_expected_modules(sft_model_not_compiled, dmd2_model_not_compiled):
125-
assert set(sft_model_not_compiled.compile_dict) == {"net"}
126-
# DMD2's model_dict contributes fake_score (+ discriminator); the base adds the teacher.
127-
assert {"net", "teacher", "fake_score"} <= set(dmd2_model_not_compiled.compile_dict)
128-
129-
130-
def test_compile_dict_excludes_ema(sft_model_not_compiled):
126+
def test_compile_excludes_ema(sft_model_not_compiled):
131127
# EMA networks live in model_dict but are weight-averaged copies that are not run
132-
# during training, so compile_dict must drop them.
128+
# during training, so apply_torch_compile must not compile them.
133129
model = sft_model_not_compiled
134130
model.use_ema = ["ema"]
135131
model.ema = torch.nn.Linear(4, 4) # any nn.Module suffices for ema_dict/model_dict
136-
assert "ema" in model.ema_dict
137-
assert "ema" in model.model_dict
138-
assert "ema" not in model.compile_dict
132+
assert "ema" in model.ema_dict and "ema" in model.model_dict
133+
134+
model.config.torch_compile_mode = "default"
135+
model.apply_torch_compile()
136+
assert _is_compiled(model.net)
137+
assert not _is_compiled(model.ema)
139138

140139

141-
def test_compile_dict_discovers_preprocessor_submodules(sft_model_not_compiled):
140+
def test_compile_discovers_preprocessor_submodules(sft_model_not_compiled):
142141
# Preprocessor wrappers (VAE, text/image encoders) are not nn.Modules themselves but
143-
# hold the actual nn.Module under an attribute; compile_dict must find those submodules.
142+
# hold the actual nn.Module under an attribute; apply_torch_compile must find and
143+
# compile those submodules.
144144
model = sft_model_not_compiled
145145

146146
class _DummyVAEWrapper: # mimics WanVideoEncoder/SDVAE (not an nn.Module)
@@ -149,13 +149,13 @@ def __init__(self):
149149
self.scaling_factor = 0.18 # non-module attributes are ignored
150150

151151
model.net.vae = _DummyVAEWrapper()
152-
keys = set(model.compile_dict)
153-
assert "vae.vae" in keys
154-
assert isinstance(model.compile_dict["vae.vae"], torch.nn.Module)
155-
156152
# An attribute that is itself an nn.Module is compiled directly under its own name.
157153
model.net.text_encoder = torch.nn.Linear(4, 4)
158-
assert "text_encoder" in model.compile_dict
154+
155+
model.config.torch_compile_mode = "default"
156+
model.apply_torch_compile()
157+
assert _is_compiled(model.net.vae.vae)
158+
assert _is_compiled(model.net.text_encoder)
159159

160160

161161
def test_sft_compiled_train_step(sft_model_compiled):

0 commit comments

Comments
 (0)