Skip to content

Fix TaylorSeer cache crash when the feature shape changes between steps - #14831

Open
hide3tu wants to merge 2 commits into
huggingface:mainfrom
hide3tu:fix-taylorseer-qwenimage21-kv-cache
Open

hide3tu wants to merge 2 commits into
huggingface:mainfrom
hide3tu:fix-taylorseer-qwenimage21-kv-cache

Conversation

@hide3tu

@hide3tu hide3tu commented Sep 21, 2026

Copy link
Copy Markdown

What does this PR do?

Fixes #14829

QwenImage21Pipeline with a TaylorSeer cache crashes on the second step when the KV cache is on (the default). With the KV cache, the transformer returns prefix + target tokens on the prefill step and target tokens only afterwards, so TaylorSeerState.update tries to difference two tensors of different sequence lengths.

This PR makes update restart the Taylor expansion from order 0 when the feature shape changes, instead of differencing against stale factors. Nothing changes when the shape is stable.

Tested on an M1 Max (MPS, bf16) only, on top of main at cc8644b. With this change the run completes, and the output is pixel-identical to use_kv_cache=False + TaylorSeer. For an edit with one reference image at 832×1216 / 40 steps, generation goes from 484 s (use_kv_cache=False + TaylorSeer) to 278 s (KV cache + TaylorSeer); the uncached baseline is 721 s.

If you would rather fix this on the model side (e.g. only passing target tokens through norm_out / proj_out on the prefill step), feel free to close this or push over it.

Self-review notes

I used Claude Code to help with this PR and ran the self-review skill on the diff.

  • Blocking issues: none found.
  • Non-blocking / left for review:
    1. The new test exercises TaylorSeerState directly. A pipeline-level regression test (tiny Qwen-Image 2.1 + TaylorSeer + KV cache) is not included, since testing.md says cache tests are added case by case.
    2. With the KV cache, the first predicted step still has to come after at least one full step in cached mode, so disable_cache_before_step needs to be >= 2. Lower values are not handled here.
    3. Only TaylorSeer was checked. Other cache hooks may hit the same shape change.
  • Dead code: none.
  • Verdict: READY

Before submitting

Who can review?

@sayakpaul

@sayakpaul
sayakpaul requested a review from DN6 September 22, 2026 09:24
torch.testing.assert_close(prediction, torch.full((1, 6, 4), 5.0))


def test_update_keeps_finite_difference_when_shape_is_stable():

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't understand the test.

Comment on lines +152 to +154
# The feature shape can change between steps, e.g. Qwen-Image 2.1 returns prefix + target
# tokens on the KV-cache prefill step and target tokens only afterwards. Stale factors
# cannot be differenced against the new features, so restart the expansion from order 0.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

And this works as expected?

@sayakpaul

Copy link
Copy Markdown
Member

Thanks for the PR. Could you also provide a minimal working code snippet and expected results (along with the time savings)?

@sayakpaul

Copy link
Copy Markdown
Member

/diffusers-bot pytest tests/models -k "taylorseer"

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

pytest tests/models -k "taylorseer" passed on GPU — view logs.

@HuggingFaceDocBuilderDev

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

state.update((features,))


def test_update_restarts_when_feature_shape_changes():

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can we structure the test in a similar manner to

class TestFluxTransformerTaylorSeerCache(FluxTransformerTesterConfig, TaylorSeerCacheTesterMixin):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think there's some confusion here. The current test follows what is here:
https://github.com/huggingface/diffusers/blob/main/tests/hooks/test_mag_cache.py

I guess what you're suggesting is to add a TestQwenImage21TaylorSeerCache class and add the respective QwenImage2.1 specific tests in it?

@hide3tu

hide3tu commented Sep 22, 2026

Copy link
Copy Markdown
Author

Thanks for running the tests! Here is a minimal snippet (the same one as in #14829):

import torch
from diffusers import QwenImage21Pipeline, TaylorSeerCacheConfig

device = "cuda" if torch.cuda.is_available() else "mps"
pipe = QwenImage21Pipeline.from_pretrained("Qwen/Qwen-Image-2.1", torch_dtype=torch.bfloat16).to(device)
pipe.transformer.enable_cache(
    TaylorSeerCacheConfig(cache_interval=3, disable_cache_before_step=3, max_order=1, use_lite_mode=True)
)
image = pipe(
    prompt="a cat sitting on a wall",
    width=512,
    height=512,
    num_inference_steps=8,
    true_cfg_scale=1.0,
    generator=torch.Generator("cpu").manual_seed(0),
).images[0]  # use_kv_cache defaults to True
image.save("out.png")

Expected results (M1 Max, MPS, bf16):

Time savings. These numbers were measured with the same fix applied as a monkeypatch (the workaround in #14829), not with this branch installed. It gives identical outputs, as above. Edit with one reference image, 832×1216, 40 steps, seed 42, cache_interval=3, one run each:

setting generation time
no cache 721 s
TaylorSeer, use_kv_cache=False 484 s
TaylorSeer + KV cache (crashes on main, runs with this fix) 278 s

For text-to-image at the same size, it goes from 615 s (no cache) to 219 s (TaylorSeer + KV cache).

The scripts I used are here: https://github.com/hide3tu/LiltingChannelLabo/tree/main/2026/09/22/qwen-image-2-1-taylorseer-cache-m1-max (repro_issue_14829.py is the snippet above, generate.py is the timing script).

@sayakpaul

Copy link
Copy Markdown
Member

Thanks! Can you also show the actual outputs?

@sayakpaul sayakpaul added this to the Release 0.41.0 milestone Sep 22, 2026
@sayakpaul sayakpaul moved this to In Progress in Diffusers Roadmap Sep 22, 2026

This branch has not been deployed

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

Labels

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

[Qwen-Image 2.1] TaylorSeer cache crashes with the default KV cache (feature shape changes after the prefill step)

4 participants