[BUG/Performance] CFG vector collapse, Turbo trajectory drift, and OOM in packed multi-image sequences
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.6k
- Forks
- 174
- PR merge metrics
- No merged PRs in 30d
Description
Summary
A deep-dive technical audit of Mage-Flow (pipeline.py and _attn_backend.py) identified five critical issues across sampling mechanics, ODE trajectory scheduling, memory safety, and CUDA kernel dispatching.
Below is a combined analysis of the root causes and their corresponding fixes.
1. Problem Description & Root Cause Analysis
1.1 CFG Renormalization Vector Collapse
- Location:
pipeline.py:_velocity() - Root Cause: Velocity vectors are rescaled per-token using
torch.norm(cond, dim=-1). In uniform or flat image regions, the conditional velocity norm approaches zero, gating the CFG vector near zero. Furthermore, per-token normalization non-uniformly skews vector directions across spatial tokens. - Impact: Feature collapse in uniform regions and spatial directional inconsistency.
1.2 Static Shift Trajectory Drift in Few-Step Turbo Schedules
- Location:
pipeline.py:build_scheduler() - Root Cause: Applying a static shift ($6.0$) to linear base sigmas for 4-step Turbo inference produces a steep drop on step 1 ($\sigma = 1.0 \to 0.667$, a 33% jump) where ODE curvature is highest.
- Impact: Trajectory drift and generation quality loss during low-step sampling schedules.
1.3 Memory Explosion During Packed Multi-Image batch_cfg
- Location:
pipeline.py:_build_pack_ctx() - Root Cause:
batch_cfg=Trueduplicates sequences across image and text modalities (e.g., $16,384$ tokens for dual $1024 \times 1024$ image pairs). FlashAttention workspace allocation scales quadratically ($O(N^2)$). - Impact: Out-Of-Memory (OOM) exceptions on 24GB GPUs (RTX 3090/4090).
1.4 Sequential Python Loop Overhead in Native SDPA Fallback
- Location:
_attn_backend.py:_resolve_sdpa() - Root Cause: When FlashAttention is unavailable, fallback SDPA execution dispatches a Python
for-loop across packed sequences ($4 \times 28 \times 30 = 3,360$ separate CUDA kernel launches per generation). - Impact: Severe CPU-bound execution bottlenecks (8–12× slowdown) on non-A100/H100 hardware.
1.5 Unchecked FlashAttention-4 Dispatch on Ampere GPUs
- Location:
_attn_backend.py:_resolve_fa4() - Root Cause: Window size parameters are normalized without validating CUDA compute capability ($< \text{SM90}$).
- Impact: Silent execution fallbacks or opaque CUTE DSL errors on SM80/SM86 architectures (A100 / RTX 3090).
2. Proposed Solutions & Refactored Code
import math
import torch
import logging
from typing import List
logger = logging.getLogger("MageFlowFixes")
# Solution 1: Global norm rescaling for CFG (direction-preserving)
def compute_velocity_field_refactored(unc: torch.Tensor, cond: torch.Tensor, cfg_scale: float, renorm: bool = True) -> torch.Tensor:
comb = unc + cfg_scale * (cond - unc)
if not renorm:
return comb
cond_norm = torch.norm(cond.float(), dim=-1, keepdim=True).mean(dim=1, keepdim=True)
comb_norm = torch.norm(comb.float(), dim=-1, keepdim=True).mean(dim=1, keepdim=True)
return comb * (cond_norm / (comb_norm + 1e-6))
# Solution 2: Cosine sigma schedule for low-step Turbo ODE trajectories
def build_turbo_sigmas_refactored(num_steps: int, shift: float = 6.0) -> List[float]:
if num_steps <= 8:
steps = torch.linspace(0, math.pi / 2, num_steps + 1)
base_sigmas = (1.0 - torch.sin(steps[:-1])).tolist()
else:
base_sigmas = torch.linspace(1.0, 1.0 / num_steps, num_steps).tolist()
return [(shift * s) / (1.0 + (shift - 1.0) * s) for s in base_sigmas] + [0.0]
# Solution 3: Memory guard for batch_cfg
def should_enable_batch_cfg(total_tokens: int, n_heads: int, head_dim: int, device: torch.device) -> bool:
if not torch.cuda.is_available():
return False
free_mem, _ = torch.cuda.mem_get_info(device)
estimated_bytes = (total_tokens ** 2) * n_heads * head_dim * 8
return estimated_bytes < (0.70 * free_mem)
# Solution 5: Architecture-aware FlashAttention dispatch
def resolve_attn_backend_safe():
if not torch.cuda.is_available():
return "sdpa"
major, _ = torch.cuda.get_device_capability()
if major >= 9:
return "fa4"
elif major >= 8:
return "fa2"
return "sdpa"
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading pipeline.py at _velocity(), build_scheduler(), and _build_pack_ctx(), then inspect _attn_backend.py at _resolve_sdpa() and _resolve_fa4(). Reproduce the four-step schedule, packed multi-image batch_cfg, fallback attention, and Ampere cases before evaluating the proposed changes; done means the listed quality, memory, dispatch, and performance failures are addressed without regressions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, pytorch
- Domain
- machine-learning, performance
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100