Skip to content

Fall back to sharding the height in the WAN VAE. - #521

Open
ninatu wants to merge 1 commit into
mainfrom
ninatu/wan_height_sharding
Open

ninatu wants to merge 1 commit into
mainfrom
ninatu/wan_height_sharding

Conversation

@ninatu

@ninatu ninatu commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator

The WAN VAE always sharded the width of its activations over the vae_spatial mesh axis. This works for the default 1280x720 landscape size, but users may also want to run inference on portrait videos 720x1280. The VAE downsamples their width to 720, 360, 180 and 90, which isn't always divisible by vae_spatial (e.g., 90 for 4).

This change adds a _spatial_sharding(mesh, shape) helper that shards height if width is not divisible by vae_spatial, but height is divisible. Videos with a divisible width keep the current behavior.

The WAN VAE always sharded the width of its activations over the
vae_spatial mesh axis. This works for the default 1280x720 landscape
size, but users may also want to run inference on portrait videos
720x1280. The VAE downsamples their width to 720, 360, 180 and 90, which
isn't always divisible by vae_spatial (e.g., 90 for 4).

This change adds a _spatial_sharding(mesh, shape) helper that shards height
if width **is not divisible** by vae_spatial, but height is divisible.
Videos with a divisible width keep the current behavior.
@ninatu
ninatu requested a review from entrpn as a code owner November 11, 2026 16:59
@github-actions

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a helper function _spatial_sharding to dynamically determine the sharding of a 5D array over the vae_spatial axis, replacing hardcoded sharding logic in __call__, _encode, and _decode. The review feedback recommends defensively checking that the input shape is 5D in _spatial_sharding to prevent unpacking errors, and addresses a potential NameError in _decode when spatial_sharding is None.

if self.mesh is not None and "vae_spatial" in self.mesh.shape
else None
)
spatial_sharding = _spatial_sharding(self.mesh, x.shape)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

There is a critical bug in _decode where if spatial_sharding is None (e.g., when running on a single device without a mesh), chunk_in_0 (line 1298) and chunk_in_1 (line 1307) are never defined. This will raise a NameError when they are passed to self.decoder on lines 1299 and 1308.

To fix this, you should define chunk_in_0 and chunk_in_1 unconditionally and apply the sharding constraint conditionally. For example:

# First chunk (i=0)
with jax.named_scope("AutoencoderKLWan_decode_chunk_0"):
  chunk_in_0 = x[:, 0:1, ...]
  if spatial_sharding is not None:
    chunk_in_0 = jax.lax.with_sharding_constraint(chunk_in_0, spatial_sharding)
  out_0, dec_feat_map, _ = self.decoder(chunk_in_0, feat_cache=dec_feat_map, feat_idx=0)

And similarly for chunk_in_1.

Comment on lines +57 to +59
if mesh is None or "vae_spatial" not in mesh.shape:
return None
_, _, height, width, _ = shape

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To prevent potential ValueError during unpacking, we should defensively check that the input shape is indeed 5D (i.e., has a length of 5) before attempting to unpack it. If it is not 5D, we can safely return None to skip applying the sharding constraint.

Suggested change
if mesh is None or "vae_spatial" not in mesh.shape:
return None
_, _, height, width, _ = shape
if mesh is None or "vae_spatial" not in mesh.shape or len(shape) != 5:
return None
_, _, height, width, _ = shape

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant