Skip to content

Add H3_ATTENTION_CACHE: stream QKV/attention-out (and optionally MLP)… - #55

Open
JunzoKamahara wants to merge 3 commits into
antirez:mainfrom
JunzoKamahara:attention-int8-cache-stream
Open

Add H3_ATTENTION_CACHE: stream QKV/attention-out (and optionally MLP)…#55
JunzoKamahara wants to merge 3 commits into
antirez:mainfrom
JunzoKamahara:attention-int8-cache-stream

Conversation

@JunzoKamahara

@JunzoKamahara JunzoKamahara commented Sep 2, 2026

Copy link
Copy Markdown

Parallels --ssd-streaming but for the int8-resident path: instead of loading BF16 and quantizing at startup, QKV/attention-output (and, with H3_INT8_STREAM_MLP=1, FC1/FC2 too) are streamed per block from a cache built once by the new build_attention_cache tool, using the same h3_gpu_quantize_weight_int8 routine as the existing resident path.

Usage:

build_attention_cache MiniMax-H3/FL2VA dit_int8_v2.cache

H3_ATTENTION_CACHE=dit_int8_v2.cache ./h3 -d MiniMax-H3 -p "..."
# add H3_INT8_STREAM_MLP=1 to also stream FC1/FC2, for the lowest DiT peak

This reaches full 50/50-block quality (no --layers skipping) at a DiT peak close to or below today's degraded-quality resident-int8 runs, since double-buffered streaming needs only two small slots instead of full block residency. With H3_INT8_STREAM_MLP additionally streaming the MLP, DiT peak drops further (~1.5 GiB at 22 frames, ~5.4 GiB at 362 frames), which is what makes a 24GB machine comfortable at ~15s/362-frame lengths.

In practice, this also makes full-depth generation substantially more usable on memory-constrained Macs: on a 24GB M5 Mac, a 5-second video can now be generated in under 10 minutes while still using all 50 DiT blocks.

The trade-off is additional SSD usage: the pre-quantized int8 cache requires approximately 18 GB of extra disk space in addition to the original model files. The cache is generated once and can then be reused across subsequent runs, avoiding repeated BF16 loading and runtime quantization.

Verified bit-for-bit identical output (matching SHA-256) against the existing resident-int8 path at matched seed, for both attention-only streaming and full attention+MLP streaming.

… int8 from a pre-quantized cache

Parallels --ssd-streaming but for the int8-resident path: instead of
loading BF16 and quantizing at startup, QKV/attention-output (and,
with H3_INT8_STREAM_MLP=1, FC1/FC2 too) are streamed per block from a
cache built once by the new build_attention_cache tool, using the same
h3_gpu_quantize_weight_int8 routine as the existing resident path.

This reaches full 50/50-block quality (no --layers skipping) at a DiT
peak close to or below today's degraded-quality resident-int8 runs,
since double-buffered streaming needs only two small slots instead of
full block residency. With H3_INT8_STREAM_MLP additionally streaming
the MLP, DiT peak drops further (~1.5 GiB at 22 frames, ~5.4 GiB at
362 frames), which is what makes a 24GB machine comfortable at
~15s/362-frame lengths.

Verified bit-for-bit identical output (matching SHA-256) against the
existing resident-int8 path at matched seed, for both attention-only
streaming and full attention+MLP streaming.
@monotected

Copy link
Copy Markdown

Hi,
It’s not very convenient to use when I need to generate a quick test video on the MFR M5 Pro (24GB).
I rebuilt it with your commit yesterday; everything works great for long videos, but for short ones, it takes significantly longer. It’s easier and faster to run them using the --ssd-streaming flag.
However, there’s a restriction in place, so I can't simply add that argument to bypass the cache; I’ve had to load the model by bypassing your implementation every time.
Could you please allow the use of the --ssd-streaming flag in automatic mode? (When this flag is set, the cache isn't used.)
Thanks!

Previously, having H3_ATTENTION_CACHE set in the environment while
also passing --ssd-streaming was a hard error (int8_qkv/
int8_attention_out are unconditionally false under --ssd-streaming,
which the cache setup rejected). That forced anyone who leaves
H3_ATTENTION_CACHE set for their usual long runs to unset it by hand
every time they want a quick --ssd-streaming test instead (reported
against PR antirez#55 by monotected: short runs got slower after adopting
H3_ATTENTION_CACHE, and --ssd-streaming was the easy way back, but
the env var stayed in the way).

--ssd-streaming is now treated as an explicit, intentional request for
a different residency mode: when both are set, a one-line stderr
notice explains H3_ATTENTION_CACHE is being ignored, and generation
proceeds via --ssd-streaming instead of failing. The other conditions
that disable int8_qkv/int8_attention_out (a short sequence, no int8
GPU support, --use-slower-bf16-qkv/-attention-output) stay hard
errors, since those describe a configuration that cannot serve the
cache at all rather than an alternate mode the user explicitly chose.

Verified: H3_ATTENTION_CACHE=dit_int8_v2.cache with --ssd-streaming
now prints the notice and completes generation instead of failing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@JunzoKamahara

JunzoKamahara commented Sep 4, 2026

Copy link
Copy Markdown
Author

Hi, thanks for the report — and sorry, the original PR description didn't actually show how to enable this feature at all (just pushed a fix for that too, see the updated description above): you need to explicitly build a cache and point H3_ATTENTION_CACHE at it:

build_attention_cache MiniMax-H3/FL2VA dit_int8_v2.cache # once
H3_ATTENTION_CACHE=dit_int8_v2.cache H3_INT8_STREAM_MLP=1 ./h3 \
  -d MiniMax-H3 -p "..." --width 512 --height 512 --frames 22 \
  --steps 4 --layers 50 --reuse 2 -o outputs/fox-quick-test.mp4

I've also pushed a separate fix (3ec6ac6) so --ssd-streaming now silently overrides H3_ATTENTION_CACHE if you ever want to bypass the cache entirely — but with H3_INT8_STREAM_MLP=1 set, you likely won't need it for short clips anymore. Let me know how it goes.

@monotected

monotected commented Sep 4, 2026

Copy link
Copy Markdown

Thanks!!!
short tests on cold (1st run)

so i made about 12 vids 6 H3_ATTENTION_CACHE +6 standart h3.c --ssd-streaming
H3_ATTENTION_CACHE really gives me 25 % speed

in t2v - no visible degrade and its fater
in ref2va i didnt understand why but :Unfortunately, there is a visible drop in quality with H3_ATTENTION_CACHE (all fine details are missing—I tried 0.3–0.5 MP).
ps
also i have 2 backed lora over the main model (maybe that is the reason of degrade )
add pics of missing parts on same seed
1pic normal legs + feet
2pic legs + transparent feet

same on 0.3-0.5 mp
Снимок экрана — 2026-09-05 в 01 41 50
Снимок экрана — 2026-09-05 в 01 42 18

cli args :
H3_ATTENTION_CACHE=./fl2va_v2.cache H3_INT8_STREAM_MLP=1 H3_ATTN_DENSE_STEPS=4 ./h3 -d ./MiniMax-DoubleLoRA-Master -p \

**now with test short video with cash i got 1m 28sec ** (Memory lifespan is barely consumed.)
N/A"
--ref-image /Users/icoidd/Desktop/minimax/start1.jpg
--ref-image /Users/icoidd/Desktop/minimax/start2.jpg
--ref-image /Users/icoidd/Desktop/minimax/start3.jpg
--ref-image /Users/icoidd/Desktop/minimax/face.jpg
--layers 50
--width 352 --height 576
--seconds 1 --steps 15 --reuse 3
--use-reference-rope
--seed 948572
-o sad_mirror_close_011.mp4
tokenizer 1/1
video VAE encoder 4/4
video VAE encoder 6/6
video VAE encoder 6/6
video VAE encoder 6/6
Qwen vision 27/27
Qwen vision 27/27
Qwen vision 27/27
Qwen vision 27/27
text encoder 50/50
refine text 1/1
precompute AdaLN 50/50
load transformer core 50/50
denoise enqueue 15/15
denoise 15/15
audio VAE 7/7
video VAE load 36/36
FFmpeg 39/39
h3: wrote sad_mirror_close_011.mp4

** and with --ssd-streaming. its 1m 50sec ** (Memory lifespan is on 15 to 18 gb in peak )
cli args :
./h3 -d ./MiniMax-DoubleLoRA-Master -p \

--ref-image /Users/icoidd/Desktop/minimax/start1.jpg
--ref-image /Users/icoidd/Desktop/minimax/start2.jpg
--ref-image /Users/icoidd/Desktop/minimax/start3.jpg
--ref-image /Users/icoidd/Desktop/minimax/face.jpg
--layers 50
--width 352 --height 576
--seconds 1 --steps 15 --reuse 3
--ssd-streaming
--use-reference-rope
--seed 948572
-o sad_mirror_close_011.mp4
tokenizer 1/1
video VAE encoder 4/4
video VAE encoder 6/6
video VAE encoder 6/6
video VAE encoder 6/6
Qwen vision 27/27
Qwen vision 27/27
Qwen vision 27/27
Qwen vision 27/27
text encoder 50/50
refine text 1/1
precompute AdaLN 50/50
load transformer core 50/50
denoise enqueue 15/15
denoise 15/15
audio VAE 7/7
video VAE load 36/36
FFmpeg 39/39
h3: wrote sad_mirror_close_011.mp4

…E_DIR

A PR antirez#55 comment from monotected reported a visible quality drop
(missing fine detail, "transparent feet") specifically in Ref2VA
generations with H3_ATTENTION_CACHE, alongside a normal 25% speedup and
no visible issue in T2V. The command they posted explains why: an
FL2VA-quantized cache (fl2va_v2.cache) streamed into a generation that
--ref-image switched to Ref2VA. attention_cache_validate() only ever
checked block_count/hidden/inner/ffn, which are identical between
FL2VA and Ref2VA (same DiT architecture) - nothing detected the
mismatch, so the wrong weights streamed in without error or crash,
just degraded output. That failure mode (works, but wrong) is worse
than a hard error.

Cache header v3 adds two fields where v2 had unused reserved[10] (40
bytes: 4 + 32 + 4, so the header stays the same total size):

- model_kind (FL2VA=1/Ref2VA=2): read back from the transformer
  directory's own last two path components (".../FL2VA/transformer" or
  ".../Ref2VA/transformer" - the exact layout h3.c's own dit_path
  selection always produces, not a guess). H3_ATTENTION_CACHE now
  refuses a mismatched cache with a specific error ("Ref2VA generation
  cannot use a FL2VA attention cache") rather than silently streaming
  it. UNKNOWN (a non-standard directory on either side) skips the
  check entirely rather than risk a false mismatch.
- model_id: h3_weight_store_fingerprint() (h3_weights.c/.h) - each
  shard's path/size/mtime hashed together (FNV-1a, non-cryptographic;
  a stat() per shard, not a read of the ~18GB of weight bytes) so it's
  cheap enough to recompute at every run. Catches a cache built against
  different/rewritten weights (e.g. a LoRA baked in after the cache was
  built). This is a warning, not a hard error, since mtimes can shift
  for benign reasons (a copied checkpoint) that model_kind never would.

This bumps H3_ATTENTION_CACHE_VERSION to 3; existing v2 caches simply
fail the version check and need rebuilding.

build_attention_cache also gains a second mode: given a model root
directory (detected by <root>/FL2VA/transformer/config.json existing)
and an output directory, it builds fl2va.cache and, if a Ref2VA
transformer is present, ref2va.cache in one pass - mirroring h3.c's own
reference_count-driven FL2VA/Ref2VA selection. The prior single
transformer-dir + single output-file usage is unchanged and still
works. A new H3_ATTENTION_CACHE_DIR env var points at such a directory
and lets h3_dit.c auto-select the matching cache by the same signal
(reference presence) h3.c already uses to pick the transformer
directory itself - the user no longer has to track that correspondence
by hand, which is very likely what led to this bug in the first place.
H3_ATTENTION_CACHE (a single file) still works for non-standard
layouts; setting both is an error.

Verified end to end: an old v2 cache is now rejected (version
mismatch). A freshly built v3 FL2VA cache's header carries model_kind=1
and a non-zero model_id at the documented byte offsets. A matching
FL2VA generation with it succeeds; the same cache with --ref-image
(Ref2VA) is rejected with the new error, without ever mis-streaming.
H3_ATTENTION_CACHE_DIR correctly auto-selects fl2va.cache for a plain
run and (correctly) fails on a missing ref2va.cache for a --ref-image
run. build_attention_cache's model-root-mode detection was checked
against a synthetic directory tree without requiring a real build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@JunzoKamahara

Copy link
Copy Markdown
Author

Thanks again — I found the cause of the Ref2VA degradation.

The cache file was valid structurally, but an FL2VA cache could also be accepted during Ref2VA generation because both transformers use the same tensor dimensions. That meant Ref2VA could silently run with FL2VA cached weights.

I changed the cache format and added automatic FL2VA / Ref2VA cache selection.

New recommended usage

Build both caches once from the model root:

./build_attention_cache
./MiniMax-DoubleLoRA-Master
./attention-cache

This creates:

attention-cache/
fl2va.cache
ref2va.cache

Then use the cache directory instead of selecting a cache file manually:

H3_ATTENTION_CACHE_DIR=./attention-cache
H3_INT8_STREAM_MLP=1
./h3 -d ./MiniMax-DoubleLoRA-Master -p "..." ...

h3.c will now choose the correct cache automatically:

  • normal T2V → "fl2va.cache"
  • "--ref-image" / Ref2VA → "ref2va.cache"

So for your previous Ref2VA command you should no longer use:

H3_ATTENTION_CACHE=./fl2va_v2.cache

Instead, build the two caches from your "MiniMax-DoubleLoRA-Master" directory and use "H3_ATTENTION_CACHE_DIR".

This is especially important in your case because your two LoRAs are baked into the model: the caches should be generated from those exact baked transformer weights.

The old single-file form is still supported:

H3_ATTENTION_CACHE=./some.cache

but the cache now records whether it is FL2VA or Ref2VA and h3.c rejects the wrong type instead of silently using it.

The cache format has also changed from v2 to v3, so existing "fl2va_v2.cache" files need to be rebuilt.

I tested:

  • FL2VA cache with T2V: OK
  • Ref2VA cache with "--ref-image": OK
  • FL2VA cache used for Ref2VA: correctly rejected
  • "H3_ATTENTION_CACHE_DIR" automatic selection for both modes: OK

Could you rebuild the caches from "MiniMax-DoubleLoRA-Master" with the command above and try the same Ref2VA seed again? That should tell us whether the missing-detail issue was entirely caused by the FL2VA/Ref2VA cache mismatch.

@monotected

monotected commented Sep 8, 2026

Copy link
Copy Markdown

Hi - sorry for late soo.... i rebuild h3.c also update and bake a new cashe
now gen time for me takes about 4-5 -7 min for 2sec 0.2mp video ( maybe new v3 code, streaming int8 matrices from the attention-cache folder creates a severe data bottleneck between the SSD and the GPU, or completely saturates the CPU cache [0.2]. The author's new patch simply failed to interface properly with your custom DoubleLoRA build architecture)

ps
so sorry that i didt use common minimax weights.
pls see args

icoidd@MacBook-Pro-icoidd h3.c % bash# 1.
rm -rf ./attention-cache/*.cache

2.

./build_attention_cache /Users/icoidd/h3.c/MiniMax-CustomLoRA-fl2va/FL2VA/transformer ./attention-cache/fl2va.cache
./build_attention_cache /Users/icoidd/h3.c/MiniMax-CustomLoRA-ref2va/Ref2VA/transformer ./attention-cache/ref2va.cache

3.

H3_ATTENTION_CACHE_DIR=./attention-cache H3_INT8_STREAM_MLP=1 ./h3 -d ./MiniMax-DoubleLoRA-Master -p "non_diegetic_music: N/A"
--ref-image /Users/icoidd/Desktop/minimax/1010.jpg
--layers 50
--width 352 --height 576
--seconds 2 --steps 15 --reuse 3
--use-reference-rope
--seed 719385
-o test_perfection_v3.mp4
zsh: command not found: bash#
zsh: command not found: #
h3: attention cache block 1/50
h3: attention cache block 2/50
h3: attention cache block 3/50
h3: attention cache block 4/50
h3: attention cache block 5/50
h3: attention cache block 6/50
h3: attention cache block 7/50
h3: attention cache block 8/50
h3: attention cache block 9/50
h3: attention cache block 10/50
h3: attention cache block 11/50
h3: attention cache block 12/50
h3: attention cache block 13/50
h3: attention cache block 14/50
h3: attention cache block 15/50
h3: attention cache block 16/50
h3: attention cache block 17/50
h3: attention cache block 18/50
h3: attention cache block 19/50
h3: attention cache block 20/50
h3: attention cache block 21/50
h3: attention cache block 22/50
h3: attention cache block 23/50
h3: attention cache block 24/50
h3: attention cache block 25/50
h3: attention cache block 26/50
h3: attention cache block 27/50
h3: attention cache block 28/50
h3: attention cache block 29/50
h3: attention cache block 30/50
h3: attention cache block 31/50
h3: attention cache block 32/50
h3: attention cache block 33/50
h3: attention cache block 34/50
h3: attention cache block 35/50
h3: attention cache block 36/50
h3: attention cache block 37/50
h3: attention cache block 38/50
h3: attention cache block 39/50
h3: attention cache block 40/50
h3: attention cache block 41/50
h3: attention cache block 42/50
h3: attention cache block 43/50
h3: attention cache block 44/50
h3: attention cache block 45/50
h3: attention cache block 46/50
h3: attention cache block 47/50
h3: attention cache block 48/50
h3: attention cache block 49/50
h3: attention cache block 50/50
h3: wrote attention cache to ./attention-cache/fl2va.cache
h3: attention cache block 1/50
h3: attention cache block 2/50
h3: attention cache block 3/50
h3: attention cache block 4/50
h3: attention cache block 5/50
h3: attention cache block 6/50
h3: attention cache block 7/50
h3: attention cache block 8/50
h3: attention cache block 9/50
h3: attention cache block 10/50
h3: attention cache block 11/50
h3: attention cache block 12/50
h3: attention cache block 13/50
h3: attention cache block 14/50
h3: attention cache block 15/50
h3: attention cache block 16/50
h3: attention cache block 17/50
h3: attention cache block 18/50
h3: attention cache block 19/50
h3: attention cache block 20/50
h3: attention cache block 21/50
h3: attention cache block 22/50
h3: attention cache block 23/50
h3: attention cache block 24/50
h3: attention cache block 25/50
h3: attention cache block 26/50
h3: attention cache block 27/50
h3: attention cache block 28/50
h3: attention cache block 29/50
h3: attention cache block 30/50
h3: attention cache block 31/50
h3: attention cache block 32/50
h3: attention cache block 33/50
h3: attention cache block 34/50
h3: attention cache block 35/50
h3: attention cache block 36/50
h3: attention cache block 37/50
h3: attention cache block 38/50
h3: attention cache block 39/50
h3: attention cache block 40/50
h3: attention cache block 41/50
h3: attention cache block 42/50
h3: attention cache block 43/50
h3: attention cache block 44/50
h3: attention cache block 45/50
h3: attention cache block 46/50
h3: attention cache block 47/50
h3: attention cache block 48/50
h3: attention cache block 49/50
h3: attention cache block 50/50
h3: wrote attention cache to ./attention-cache/ref2va.cache
zsh: command not found: #
tokenizer 1/1
video VAE encoder 6/6
Qwen vision 27/27
text encoder 50/50
refine text 1/1
precompute AdaLN 50/50
load transformer core 50/50
denoise enqueue 15/15
denoise 15/15
audio VAE 7/7
video VAE load 36/36
FFmpeg 56/56
h3: wrote test_perfection_v3.mp4. = 7min vs --ssd-stream 1.4min

@monotected

monotected commented Sep 9, 2026

Copy link
Copy Markdown

i allready rebuild with original weights = same time 5-7 min
(it also work with --ssd-streaming together takes 1.28min but i didnt understand - does it use cache v3 or not )

@JunzoKamahara

Copy link
Copy Markdown
Author

Thanks for testing this.

A couple of notes for the benchmark:

  • "build_attention_cache" only needs to be run once per model. I have already built the cache from the original model weights, so there is no need to rebuild it for each run.
  • On my machine, using your prompt, the PR version took about 129 seconds, while "--ssd-streaming" took about 158 seconds.
  • When measuring the total execution time, please prepend "/usr/bin/time" to the "./h3" command, for example:

"/usr/bin/time ./h3 ..."

That should make the comparison easier and more consistent.

@monotected

monotected commented Sep 9, 2026

Copy link
Copy Markdown

Спасибо за тестирование.

Несколько замечаний по поводу теста производительности:

  • Функцию "build_attention_cache" нужно запускать только один раз для каждой модели. Я уже создал кэш на основе исходных весов модели, поэтому нет необходимости перестраивать его при каждом запуске.
  • На моей машине при использовании вашей команды выполнение версии PR заняло около 129 секунд, а "--ssd-streaming" — около 158 секунд.
  • При измерении общего времени выполнения, пожалуйста, добавьте перед командой "./h3" префикс "/usr/bin/time", например:

"/usr/bin/time ./h3 ..."

Это должно упростить и сделать сравнение более последовательным.
Thanx later this nigh ill try

.....some kind a bud on my side
icoidd@MacBook-Pro-icoidd h3.c % H3_ATTENTION_CACHE_DIR=./attention-cache H3_INT8_STREAM_MLP=1 /usr/bin/time ./h3 -d ./MiniMax-DoubleLoRA-Master -p "non_diegetic_music: N/A"
--ref-image /Users/icoidd/Desktop/minimax/1010.jpg
--layers 50
--width 352 --height 576
--seconds 2 --steps 15 --reuse 3
--use-reference-rope
--seed 719385
-o test_perfection_v3.mp4

tokenizer 1/1
video VAE encoder 6/6
Qwen vision 27/27
text encoder 50/50
refine text 1/1
precompute AdaLN 50/50
load transformer core 50/50
denoise enqueue 15/15
denoise 15/15
audio VAE 7/7
video VAE load 36/36
FFmpeg 56/56
h3: wrote test_perfection_v3.mp4
505.26 real 1.31 user 78.63 sys

@monotected

Copy link
Copy Markdown

thanx!! /issue was on my syde now its great no quality loss
icoidd@MacBook-Pro-icoidd h3.c % H3_ATTENTION_CACHE_DIR=./attention-cache H3_INT8_STREAM_MLP=1 /usr/bin/time ./h3 -d ./MiniMax-DoubleLoRA-Master -p "non_diegetic_music: N/A" --ref-image /Users/icoidd/Desktop/minimax/1010.jpg --layers 50 --width 352 --height 576 --seconds 2 --steps 15 --reuse 3 --use-reference-rope --seed 719385 -o test_perfection_v3.mp4

tokenizer 1/1
video VAE encoder 6/6
Qwen vision 27/27
text encoder 50/50
h3: warning: attention cache ./attention-cache/ref2va.cache's model fingerprint does not match the loaded checkpoint (different weights, a LoRA baked in after the cache was built, or weights rewritten since) - results may be wrong; rebuild the cache if unsure
refine text 1/1
precompute AdaLN 50/50
load transformer core 50/50
denoise enqueue 15/15
denoise 15/15
audio VAE 7/7
video VAE load 36/36
FFmpeg 56/56
h3: wrote test_perfection_v3.mp4
80.21 real 1.27 user 34.31 sys
icoidd@MacBook-Pro-icoidd h3.c %

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.

2 participants