[bugfix] v2: MatrixGame2/3 causal-loop progress counter + MG3 patch alignment
MatrixGame2 (causal DMD loop): bump st.step_idx on every executed work unit (each DMD step and each clean-context pass). The loop drives its own control flow off block_idx/dmd_idx/phase, but the runtime's no-progress watchdog keys on st.step_idx, so a multi-block causal rollout was seen as stalled. Mirrors what every other recipe loop does. MatrixGame3 (5B WanModel): patch-align the latent H/W (patch_size (1,2,2)) before denoise. The model folds (H/2, W/2) tokens, so an odd latent dim made the unpatchified velocity come back one row/col short of the noise latent. Crop to (latent // patch) * patch, faithful to MatrixGame3DenoisingStage. v2 mini: 240 passed.
This commit is contained in:
@@ -291,6 +291,11 @@ class MatrixGame2CausalDMDLoop:
|
||||
# advance #
|
||||
# --------------------------------------------------------------------- #
|
||||
def advance(self, st: LoopState, result: StepResult) -> LoopState:
|
||||
# Monotonic progress counter: this loop drives control flow off block_idx/dmd_idx/phase (in
|
||||
# scratch), but the runtime's no-progress watchdog (engine ProgramRunner._progress) keys on
|
||||
# st.step_idx. Bump it on EVERY executed work unit (each DMD step AND each clean-context pass)
|
||||
# so a multi-block causal rollout is seen to advance — every other recipe loop does the same.
|
||||
st.step_idx += 1
|
||||
out = result.output
|
||||
start, num = out["start"], out["num"]
|
||||
# Write the (denoised or unchanged) block back into the full latent.
|
||||
|
||||
@@ -60,6 +60,12 @@ MG3_NUM_TRAIN_TIMESTEPS = 1000 # FlowUniPC timestep ~ sigma * num_train_timeste
|
||||
MG3_CLIP_FRAME = 56
|
||||
MG3_FIRST_CLIP_FRAME = MG3_CLIP_FRAME + 1 # 57
|
||||
MG3_PAST_FRAME = 16
|
||||
# DiT patch stride on the spatial latent dims (patch_size (1,2,2)). The 5B MatrixGame3WanModel folds
|
||||
# (H/2, W/2) tokens, so the latent H/W must be patch-aligned (even) before denoise or the unpatchified
|
||||
# velocity comes back one row/col short of the noise latent (faithful to MatrixGame3DenoisingStage's
|
||||
# ``latent_h_aligned = (latent_h // patch_h) * patch_h`` crop). 720px -> latent_h 45 (odd) -> 44.
|
||||
MG3_PATCH_H = 2
|
||||
MG3_PATCH_W = 2
|
||||
|
||||
|
||||
def _toy_latent_shape(req) -> tuple[int, int, int, int]:
|
||||
@@ -76,7 +82,14 @@ def _toy_latent_shape(req) -> tuple[int, int, int, int]:
|
||||
def _gpu_latent_shape(req, channels: int, spatial_ratio: int, temporal_ratio: int) -> tuple[int, int, int, int]:
|
||||
d = req.diffusion
|
||||
t = (max(1, d.num_frames) - 1) // temporal_ratio + 1
|
||||
return (channels, max(1, t), max(1, d.height // spatial_ratio), max(1, d.width // spatial_ratio))
|
||||
h = max(1, d.height // spatial_ratio)
|
||||
w = max(1, d.width // spatial_ratio)
|
||||
# Patch-align the spatial latent dims to the DiT patch stride (faithful to MatrixGame3DenoisingStage):
|
||||
# an odd latent_h/w (e.g. 720px -> 45) would otherwise leave the unpatchified velocity one row short
|
||||
# of the noise latent and break the flow-match step's elementwise add.
|
||||
h = max(MG3_PATCH_H, (h // MG3_PATCH_H) * MG3_PATCH_H)
|
||||
w = max(MG3_PATCH_W, (w // MG3_PATCH_W) * MG3_PATCH_W)
|
||||
return (channels, max(1, t), h, w)
|
||||
|
||||
|
||||
def _cond_compatible(latent: np.ndarray, img_cond: np.ndarray) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user