Skip to content

strip padding from text latent cache for variable length models - #1345

Merged
dxqb merged 6 commits into
Nerogar:mergefrom
BitcrushedHeart:zimagecache
Mar 17, 2026
Merged

dxqb merged 6 commits into
Nerogar:mergefrom
BitcrushedHeart:zimagecache

Conversation

@BitcrushedHeart

@BitcrushedHeart BitcrushedHeart commented Feb 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Z-Image text caches pad all sequences to 512 tokens, but the padding is stripped at training time anyway (ZImageModel.encode_text() masks it out via tokens_mask)
  • This adds two lightweight pipeline modules that strip padding before DiskCache saves and restore it after DiskCache loads, dramatically reducing text cache size on disk with no change to training behavior
  • Only Z-Image is affected - no other model data loaders, mgds, or training code is modified

Details

  • StripPaddedTokens (new, in modules/dataLoader/zimage/): inserted after EncodeQwenText in _preparation_modules(). Uses the attention mask to boolean-index tokens, tokens_mask, and text_encoder_hidden_state, keeping only real token positions before caching.
  • PadTokens (new, in modules/dataLoader/zimage/): inserted at the start of _output_modules(). Pads stripped tensors back to PROMPT_MAX_LENGTH (512) using F.pad so torch.stack() batching still works. Old caches are compatible.

Z-Image text caches pad all sequences to 512 tokens, but the padding
is stripped at training time anyway. This removes padding before caching
and restores it after loading, dramatically reducing text cache size on
disk (typically ~80% for average-length prompts) with no change to
training behavior. Only Z-Image is affected.
@BitcrushedHeart

Copy link
Copy Markdown
Contributor Author

Tested. Works on Z-Image. Works with #1346 and Nerogar/mgds#44.

@dxqb

dxqb commented Feb 27, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the PR!
Could you please have a look at this and check whether that changes anything for this PR? Tongyi-MAI/Z-Image#131 (comment)

Z-Image is unusual in that there are two types of padding tokens, inner padding and outer padding. Inner padding is not masked for attention (and must therefore not be cut!), outer padding is masked.

@BitcrushedHeart

BitcrushedHeart commented Feb 27, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks for the PR! Could you please have a look at this and check whether that changes anything for this PR? Tongyi-MAI/Z-Image#131 (comment)

Z-Image is unusual in that there are two types of padding tokens, inner padding and outer padding. Inner padding is not masked for attention (and must therefore not be cut!), outer padding is masked.

Thanks for flagging! I checked the linked issue & inner padding (which aligns sequences to SEQ_MULTI_OF) has attention_mask=1. StripPaddedTokens only removes positions where tokens_mask == 0 (outer padding), so inner padding is preserved. This matches the same boolean-mask filtering that encode_text() already applies at lines 171-172 of ZImageModel.py. No changes needed.

@dxqb dxqb left a comment

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.

Thanks.
Please see my code comments.
I think the same could work for other models, not only Z-Image:

  • Chroma
  • Qwen
  • probably others

it won't work for

  • SDXL
  • Flux1
  • Flux2

Would you like to implement it for those models as well?

Comment thread modules/dataLoader/zimage/PadTokens.py Resolved
Addresses review feedback: renamed to PruneMaskedTokens/PadMaskedTokens, moved to MGDS (mgds#47), reorganized dataloader code, and added latent cache pruning for Chroma and Qwen.
@BitcrushedHeart
BitcrushedHeart requested a review from dxqb February 27, 2026 18:37
@dxqb

dxqb commented Mar 3, 2026

Copy link
Copy Markdown
Collaborator

@dxqb dxqb changed the title strip padding from Z-Image text latent cache strip padding from text latent cache for variable length models Mar 3, 2026

@dxqb dxqb left a comment

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.

looks good to me, but I am a bit hesitant to merge this: any silent errors in this PR will be difficult to detect but screws up text conditioning and have very unexpected effects.

any way this can be thoroughly tested?

@dxqb

dxqb commented Mar 15, 2026

Copy link
Copy Markdown
Collaborator

for a small dataset captioned by an AI, this reduced total cache size from 98 MB to 14 MB on Qwen

@dxqb

dxqb commented Mar 15, 2026

Copy link
Copy Markdown
Collaborator

tested for all 3 models

identical for z-Image, identical for unmasked tokens on the other models (but if there isn't a bug in diffusers for attention masking, that's okay)

can be merged once Nerogar/mgds#47 is finished

here is how I tested:

                filename = f"text-{train_progress.global_step}.pt"
                if False:
                    torch.save((text_encoder_output, text_attention_mask), filename)
                else:
                    text_encoder_output2, text_attention_mask2 = torch.load(filename)
                    identical = torch.equal(text_encoder_output, text_encoder_output2)
                    masked = torch.equal(text_encoder_output[text_attention_mask], text_encoder_output2[text_attention_mask2])
                    print("\n", identical, masked)
                    assert masked

@dxqb dxqb added the merging last steps before merge label Mar 15, 2026
@dxqb
dxqb changed the base branch from master to merge March 17, 2026 06:38
@dxqb
dxqb merged commit 35023ee into Nerogar:merge Mar 17, 2026
1 check passed
Calamdor added a commit to Calamdor/OneTrainer that referenced this pull request Mar 20, 2026
Port of BitcrushedHeart's Nerogar#1345 to WanBaseDataLoader. umt5-xxl uses a
512-token max length but typical prompts are 80-250 tokens; caching the
full padded tensor wastes significant disk space. PruneMaskedTokens
strips padding before writing to cache; PadMaskedTokens restores to 512
on load. Guarded by config.latent_caching (always true for Wan LoRA).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Calamdor added a commit to Calamdor/OneTrainer that referenced this pull request Mar 28, 2026
Port of BitcrushedHeart's Nerogar#1345 to WanBaseDataLoader. umt5-xxl uses a
512-token max length but typical prompts are 80-250 tokens; caching the
full padded tensor wastes significant disk space. PruneMaskedTokens
strips padding before writing to cache; PadMaskedTokens restores to 512
on load. Guarded by config.latent_caching (always true for Wan LoRA).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@BitcrushedHeart
BitcrushedHeart deleted the zimagecache branch March 29, 2026 15:33
BitcrushedHeart added a commit to BitcrushedHeart/OneTrainer that referenced this pull request Jun 20, 2026
…gar#1345)

---------

Co-authored-by: BitcrushedHeart <215311041+BitcrushedHeart@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merging last steps before merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants