Skip to content

[None][feat] Qwen-Image TeaCache/Cache-DiT Support - #16339

Open
o-stoner wants to merge 5 commits into
NVIDIA:mainfrom
o-stoner:user/o-stoner/visual-gen-qwenimage-caching
Open

[None][feat] Qwen-Image TeaCache/Cache-DiT Support#16339
o-stoner wants to merge 5 commits into
NVIDIA:mainfrom
o-stoner:user/o-stoner/visual-gen-qwenimage-caching

Conversation

@o-stoner

@o-stoner o-stoner commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added TeaCache acceleration support for Qwen-Image generation.
    • Added Cache-DiT support for Qwen-Image, improving reuse of computation during generation.
    • Added configuration handling for separate conditional and unconditional generation passes.
  • Documentation

    • Updated the feature matrix to show TeaCache and Cache-DiT support for Qwen-Image.
    • Added guidance for tuning Cache-DiT quality with residual_diff_threshold.

Description

Enables both TeaCache and Cache-DiT support for Qwen-Image.

Example quality/perf comparison on B200 (umb-b200-237):

"a cat sitting on a bench in a garden"

Default:
Configs: 1328×1328, 30 steps, seed 42, all other params set at default value
E2E pipeline time: 6.167s
qwen_image_baseline_1328

TeaCache:
Configs: 1328×1328, 30 steps, seed 42, teacache_thresh=0.2, all other params set at default value
E2E pipeline time: 4.493s (1.37x default)
LPIPS score against default: 0.0210
qwen_image_teacache_1328

Cache-DiT:
Configs: 1328×1328, 30 steps, seed 42, residual_diff_threshold=0.16 (lower than default for better quality), all other params set at default value
E2E pipeline time: 4.390s (1.40x default)
LPIPS score against default: 0.0372
qwen_image_cache_dit_r0 16_1328

Our findings show that the LPIPS scores are low enough that we could use more aggressive TeaCache/Cache-DiT configs to enable more caching than the example shown above, leading to faster E2E perf.

Test Coverage

  1. test_teacache.py : TestQwenImageTeacacheTable: 3 new unit tests covering Qwen-Image coefficient resolution from checkpoint path, rejection of unrelated paths, and user-supplied coefficients taking precedence over the built-in table.
  2. test_cache_dit.py : TestCacheDiTRealPipelineForward: 1 new GPU integration test verifying that Cache-DiT skips at least one transformer block during a real 16-step Qwen-Image forward pass.

PR Checklist

Please review the following before submitting your PR:

  • PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.

  • PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.

  • Test cases are provided for new code paths (see test instructions)

  • If PR introduces API changes, an appropriate PR label is added - either api-compatible or api-breaking. For api-breaking, include BREAKING in the PR title.

  • Any new dependencies have been scanned for license and vulnerabilities

  • CODEOWNERS updated if ownership changes

  • Documentation updated as needed

  • Update tava architecture diagram if there is a significant design change in PR.

  • The reviewers assigned automatically/manually are appropriate for the PR.

  • Please check this after reviewing the above items as appropriate for this PR.

GitHub Bot Help

To see a list of available CI bot commands, please comment /bot help.

o-stoner added 2 commits July 13, 2026 13:39
Signed-off-by: Olivia Stoner <245287810+o-stoner@users.noreply.github.com>
Signed-off-by: Olivia Stoner <245287810+o-stoner@users.noreply.github.com>
@o-stoner
o-stoner requested review from a team as code owners July 13, 2026 21:49
@o-stoner
o-stoner requested review from kaiyux and laikhtewari July 13, 2026 21:49
@o-stoner

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #59030 [ run ] triggered by Bot. Commit: e07f980 Link to invocation

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Qwen-Image now supports TeaCache and Cache-DiT during visual generation. The pipeline manages cache state across true CFG passes, Cache-DiT receives a dedicated enabler, tests cover integration and coefficient selection, and documentation records support and tuning guidance.

Changes

Qwen-Image cache acceleration

Layer / File(s) Summary
Cache-DiT registration and refresh
tensorrt_llm/_torch/visual_gen/cache/cache_dit_enablers.py
Adds a Qwen-Image-specific Cache-DiT enabler, optional TaylorSeer setup, refresh handling, and pipeline dispatch registration.
TeaCache pipeline lifecycle
tensorrt_llm/_torch/visual_gen/models/qwen_image/pipeline_qwen_image.py
Adds Qwen-Image TeaCache coefficients, timestep extraction, cache initialization, per-request reset, CFG branch switching, and statistics logging.
Cache validation and feature documentation
tests/unittest/_torch/visual_gen/test_cache_dit.py, tests/unittest/_torch/visual_gen/test_teacache.py, docs/source/models/visual-generation.md
Adds Qwen-Image checkpoint resolution and Cache-DiT integration coverage, validates TeaCache coefficient selection, and documents support and threshold tuning.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Request
  participant QwenImagePipeline
  participant TeaCache
  participant CacheDiT
  participant QwenImageTransformer2DModel
  Request->>QwenImagePipeline: start generation
  QwenImagePipeline->>TeaCache: reset cache state
  QwenImagePipeline->>CacheDiT: refresh cache context
  QwenImagePipeline->>QwenImageTransformer2DModel: run conditional forward
  QwenImagePipeline->>QwenImageTransformer2DModel: run unconditional forward
  QwenImagePipeline->>TeaCache: collect cache statistics
Loading

Suggested reviewers: kaiyux, laikhtewari, bobboli, zhenhuaw-me, pst2154

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise, formatted, and accurately summarizes the main change: Qwen-Image TeaCache and Cache-DiT support.
Description check ✅ Passed The description includes the required sections and provides a clear summary, test coverage, and checklist with no major omissions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tensorrt_llm/_torch/visual_gen/cache/cache_dit_enablers.py`:
- Around line 347-376: Verify Cache-DiT’s DBCacheConfig behavior for
Qwen-Image’s two separate CFG passes, then update
enable_cache_dit_for_qwen_image() to pass enable_separate_cfg=True to
_build_db_cache_config() if automatic isolation is not guaranteed; otherwise
document or preserve the confirmed default behavior. In pipeline_qwen_image.py,
retain the existing _cache_branch handling unless verification shows it must be
coordinated with Cache-DiT.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a7e0347c-bdc1-421a-a17f-7b3fcdb45b39

📥 Commits

Reviewing files that changed from the base of the PR and between 43dfc81 and e07f980.

📒 Files selected for processing (5)
  • docs/source/models/visual-generation.md
  • tensorrt_llm/_torch/visual_gen/cache/cache_dit_enablers.py
  • tensorrt_llm/_torch/visual_gen/models/qwen_image/pipeline_qwen_image.py
  • tests/unittest/_torch/visual_gen/test_cache_dit.py
  • tests/unittest/_torch/visual_gen/test_teacache.py

Comment thread tensorrt_llm/_torch/visual_gen/cache/cache_dit_enablers.py
Signed-off-by: Olivia Stoner <245287810+o-stoner@users.noreply.github.com>
@o-stoner

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #59034 [ run ] triggered by Bot. Commit: cef291c Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #59030 [ run ] completed with state ABORTED. Commit: e07f980

Link to invocation

zhenhuaw-me
zhenhuaw-me previously approved these changes Jul 14, 2026
Comment thread tensorrt_llm/_torch/visual_gen/cache/cache_dit_enablers.py Outdated
timestep = t.expand(latents.shape[0]).to(latents.dtype)

# Conditional (positive) branch.
if cache_acc is not None:

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.

Should we use the same conditions as above?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed, along with the other cache guard inconsistencies, by introducing cache_on = self.cache_enabled before the loop. All branch guards now use the same condition.

latents = latents.to(latents_dtype)

if getattr(self, "rank", 0) == 0:
if cache_acc is not None and cache_acc.is_enabled():

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.

Maybe we can have something like self.cache_enabled()

@o-stoner o-stoner Jul 15, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done, added cache_enabled as a property on QwenImagePipeline and used cache_on = self.cache_enabled before the loop so all sites share a single consistent check.

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #59034 [ run ] completed with state SUCCESS. Commit: cef291c
/LLM/main/L0_MergeRequest_PR pipeline #47560 completed with status: 'SUCCESS'

CI Report

Link to invocation

Comment thread tensorrt_llm/_torch/visual_gen/cache/cache_dit_enablers.py Outdated
Comment thread tensorrt_llm/_torch/visual_gen/models/qwen_image/pipeline_qwen_image.py Outdated
Signed-off-by: Olivia Stoner <245287810+o-stoner@users.noreply.github.com>
@o-stoner
o-stoner force-pushed the user/o-stoner/visual-gen-qwenimage-caching branch from cef291c to cd065a7 Compare July 15, 2026 18:04
Signed-off-by: Olivia Stoner <245287810+o-stoner@users.noreply.github.com>
@o-stoner

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #59525 [ run ] triggered by Bot. Commit: 88c4ddd Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #59525 [ run ] completed with state SUCCESS. Commit: 88c4ddd
/LLM/main/L0_MergeRequest_PR pipeline #47978 completed with status: 'SUCCESS'

CI Report

Link to invocation

@zhenhuaw-me zhenhuaw-me left a comment

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.

LGTM with some naming issues.

Please always feel free to resolve the threads if the changes reflect the review comments.

Comment on lines 25 to 30
# Batched CFG: default enable_separate_cfg False (single cond+uncond batch).
# Qwen-Image uses non-batched CFG (two separate forward passes),
# so it has no enable_separate_cfg flag here.
_WAN_CFG_DEFAULT = False
_FLUX_CFG_DEFAULT = False
_LTX2_CFG_DEFAULT = False

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.

Suggested change
# Batched CFG: default enable_separate_cfg False (single cond+uncond batch).
# Qwen-Image uses non-batched CFG (two separate forward passes),
# so it has no enable_separate_cfg flag here.
_WAN_CFG_DEFAULT = False
_FLUX_CFG_DEFAULT = False
_LTX2_CFG_DEFAULT = False
# Batched CFG: default enable_separate_cfg False (single cond+uncond batch).
# Qwen-Image uses non-batched CFG (two separate forward passes),
# so it has no enable_separate_cfg flag here.
_WAN_BATCHED_CFG_DEFAULT = False
_FLUX_BATCHED_CFG_DEFAULT = False
_LTX2_BATCHED_CFG_DEFAULT = False

(I should raise this in the previous round review, sorry) The semantic is "batch_cfg", in this case, can we rename to like this?

f"W={db_cfg.max_warmup_steps}",
)

disable_target = cache_dit.enable_cache(

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.

(still naming confusions...) In first read, it's confusing to assign the return values of enable_xyz() to objects named like disable_target. It seems the return values is the original pipeline according to https://github.com/vipshop/cache-dit/blob/ad9335fdcc7d648b50a7d4ff46b1f25e2abdaf45/src/cache_dit/caching/cache_interface.py#L82 . Did I misread anything?

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants