Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
from __future__ import annotations
from typing import TYPE_CHECKING , Union
from comfy_api . latest import io , ComfyExtension
import comfy . patcher_extension
import logging
import torch
import comfy . model_patcher
if TYPE_CHECKING :
from uuid import UUID
2026-02-06 07:43:09 +02:00
def _extract_tensor ( data , output_channels ) :
""" Extract tensor from data, handling both single tensors and lists. """
if isinstance ( data , list ) :
# LTX2 AV tensors: [video, audio]
return data [ 0 ] [ : , : output_channels ] , data [ 1 ] [ : , : output_channels ]
return data [ : , : output_channels ] , None
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
def easycache_forward_wrapper ( executor , * args , * * kwargs ) :
# get values from args
transformer_options : dict [ str ] = args [ - 1 ]
if not isinstance ( transformer_options , dict ) :
transformer_options = kwargs . get ( " transformer_options " )
if not transformer_options :
transformer_options = args [ - 2 ]
easycache : EasyCacheHolder = transformer_options [ " easycache " ]
2026-02-06 07:43:09 +02:00
x , ax = _extract_tensor ( args [ 0 ] , easycache . output_channels )
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
sigmas = transformer_options [ " sigmas " ]
uuids = transformer_options [ " uuids " ]
if sigmas is not None and easycache . is_past_end_timestep ( sigmas ) :
return executor ( * args , * * kwargs )
# prepare next x_prev
has_first_cond_uuid = easycache . has_first_cond_uuid ( uuids )
next_x_prev = x
input_change = None
do_easycache = easycache . should_do_easycache ( sigmas )
if do_easycache :
2025-08-24 13:29:49 -06:00
easycache . check_metadata ( x )
2026-01-21 20:01:35 -08:00
# if there isn't a cache diff for current conds, we cannot skip this step
can_apply_cache_diff = easycache . can_apply_cache_diff ( uuids )
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
# if first cond marked this step for skipping, skip it and use appropriate cached values
2026-01-21 20:01:35 -08:00
if easycache . skip_current_step and can_apply_cache_diff :
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
if easycache . verbose :
logging . info ( f " EasyCache [verbose] - was marked to skip this step by { easycache . first_cond_uuid } . Present uuids: { uuids } " )
2026-02-06 07:43:09 +02:00
result = easycache . apply_cache_diff ( x , uuids )
if ax is not None :
result_audio = easycache . apply_cache_diff ( ax , uuids , is_audio = True )
return [ result , result_audio ]
return result
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
if easycache . initial_step :
easycache . first_cond_uuid = uuids [ 0 ]
has_first_cond_uuid = easycache . has_first_cond_uuid ( uuids )
easycache . initial_step = False
if has_first_cond_uuid :
if easycache . has_x_prev_subsampled ( ) :
input_change = ( easycache . subsample ( x , uuids , clone = False ) - easycache . x_prev_subsampled ) . flatten ( ) . abs ( ) . mean ( )
if easycache . has_output_prev_norm ( ) and easycache . has_relative_transformation_rate ( ) :
approx_output_change_rate = ( easycache . relative_transformation_rate * input_change ) / easycache . output_prev_norm
easycache . cumulative_change_rate + = approx_output_change_rate
2026-01-21 20:01:35 -08:00
if easycache . cumulative_change_rate < easycache . reuse_threshold and can_apply_cache_diff :
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
if easycache . verbose :
logging . info ( f " EasyCache [verbose] - skipping step; cumulative_change_rate: { easycache . cumulative_change_rate } , reuse_threshold: { easycache . reuse_threshold } " )
# other conds should also skip this step, and instead use their cached values
easycache . skip_current_step = True
2026-02-06 07:43:09 +02:00
result = easycache . apply_cache_diff ( x , uuids )
if ax is not None :
result_audio = easycache . apply_cache_diff ( ax , uuids , is_audio = True )
return [ result , result_audio ]
return result
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
else :
if easycache . verbose :
logging . info ( f " EasyCache [verbose] - NOT skipping step; cumulative_change_rate: { easycache . cumulative_change_rate } , reuse_threshold: { easycache . reuse_threshold } " )
easycache . cumulative_change_rate = 0.0
2026-02-06 07:43:09 +02:00
full_output : torch . Tensor = executor ( * args , * * kwargs )
output , audio_output = _extract_tensor ( full_output , easycache . output_channels )
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
if has_first_cond_uuid and easycache . has_output_prev_norm ( ) :
output_change = ( easycache . subsample ( output , uuids , clone = False ) - easycache . output_prev_subsampled ) . flatten ( ) . abs ( ) . mean ( )
if easycache . verbose :
output_change_rate = output_change / easycache . output_prev_norm
easycache . output_change_rates . append ( output_change_rate . item ( ) )
if easycache . has_relative_transformation_rate ( ) :
approx_output_change_rate = ( easycache . relative_transformation_rate * input_change ) / easycache . output_prev_norm
easycache . approx_output_change_rates . append ( approx_output_change_rate . item ( ) )
if easycache . verbose :
logging . info ( f " EasyCache [verbose] - approx_output_change_rate: { approx_output_change_rate } " )
if input_change is not None :
easycache . relative_transformation_rate = output_change / input_change
if easycache . verbose :
logging . info ( f " EasyCache [verbose] - output_change_rate: { output_change_rate } " )
# TODO: allow cache_diff to be offloaded
easycache . update_cache_diff ( output , next_x_prev , uuids )
2026-02-06 07:43:09 +02:00
if audio_output is not None :
easycache . update_cache_diff ( audio_output , ax , uuids , is_audio = True )
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
if has_first_cond_uuid :
easycache . x_prev_subsampled = easycache . subsample ( next_x_prev , uuids )
easycache . output_prev_subsampled = easycache . subsample ( output , uuids )
easycache . output_prev_norm = output . flatten ( ) . abs ( ) . mean ( )
if easycache . verbose :
logging . info ( f " EasyCache [verbose] - x_prev_subsampled: { easycache . x_prev_subsampled . shape } " )
2026-02-06 07:43:09 +02:00
return full_output
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
def lazycache_predict_noise_wrapper ( executor , * args , * * kwargs ) :
# get values from args
timestep : float = args [ 1 ]
model_options : dict [ str ] = args [ 2 ]
easycache : LazyCacheHolder = model_options [ " transformer_options " ] [ " easycache " ]
if easycache . is_past_end_timestep ( timestep ) :
return executor ( * args , * * kwargs )
2026-02-07 21:25:30 +02:00
x : torch . Tensor = args [ 0 ] [ : , : easycache . output_channels ]
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
# prepare next x_prev
next_x_prev = x
input_change = None
do_easycache = easycache . should_do_easycache ( timestep )
if do_easycache :
2025-08-24 13:29:49 -06:00
easycache . check_metadata ( x )
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
if easycache . has_x_prev_subsampled ( ) :
if easycache . has_x_prev_subsampled ( ) :
input_change = ( easycache . subsample ( x , clone = False ) - easycache . x_prev_subsampled ) . flatten ( ) . abs ( ) . mean ( )
if easycache . has_output_prev_norm ( ) and easycache . has_relative_transformation_rate ( ) :
approx_output_change_rate = ( easycache . relative_transformation_rate * input_change ) / easycache . output_prev_norm
easycache . cumulative_change_rate + = approx_output_change_rate
if easycache . cumulative_change_rate < easycache . reuse_threshold :
if easycache . verbose :
logging . info ( f " LazyCache [verbose] - skipping step; cumulative_change_rate: { easycache . cumulative_change_rate } , reuse_threshold: { easycache . reuse_threshold } " )
# other conds should also skip this step, and instead use their cached values
easycache . skip_current_step = True
return easycache . apply_cache_diff ( x )
else :
if easycache . verbose :
logging . info ( f " LazyCache [verbose] - NOT skipping step; cumulative_change_rate: { easycache . cumulative_change_rate } , reuse_threshold: { easycache . reuse_threshold } " )
easycache . cumulative_change_rate = 0.0
output : torch . Tensor = executor ( * args , * * kwargs )
if easycache . has_output_prev_norm ( ) :
output_change = ( easycache . subsample ( output , clone = False ) - easycache . output_prev_subsampled ) . flatten ( ) . abs ( ) . mean ( )
if easycache . verbose :
output_change_rate = output_change / easycache . output_prev_norm
easycache . output_change_rates . append ( output_change_rate . item ( ) )
if easycache . has_relative_transformation_rate ( ) :
approx_output_change_rate = ( easycache . relative_transformation_rate * input_change ) / easycache . output_prev_norm
easycache . approx_output_change_rates . append ( approx_output_change_rate . item ( ) )
if easycache . verbose :
logging . info ( f " LazyCache [verbose] - approx_output_change_rate: { approx_output_change_rate } " )
if input_change is not None :
easycache . relative_transformation_rate = output_change / input_change
if easycache . verbose :
logging . info ( f " LazyCache [verbose] - output_change_rate: { output_change_rate } " )
# TODO: allow cache_diff to be offloaded
easycache . update_cache_diff ( output , next_x_prev )
easycache . x_prev_subsampled = easycache . subsample ( next_x_prev )
easycache . output_prev_subsampled = easycache . subsample ( output )
easycache . output_prev_norm = output . flatten ( ) . abs ( ) . mean ( )
if easycache . verbose :
logging . info ( f " LazyCache [verbose] - x_prev_subsampled: { easycache . x_prev_subsampled . shape } " )
return output
def easycache_calc_cond_batch_wrapper ( executor , * args , * * kwargs ) :
model_options = args [ - 1 ]
easycache : EasyCacheHolder = model_options [ " transformer_options " ] [ " easycache " ]
easycache . skip_current_step = False
# TODO: check if first_cond_uuid is active at this timestep; otherwise, EasyCache needs to be partially reset
return executor ( * args , * * kwargs )
def easycache_sample_wrapper ( executor , * args , * * kwargs ) :
"""
This OUTER_SAMPLE wrapper makes sure easycache is prepped for current run , and all memory usage is cleared at the end .
"""
try :
guider = executor . class_obj
orig_model_options = guider . model_options
guider . model_options = comfy . model_patcher . create_model_options_clone ( orig_model_options )
# clone and prepare timesteps
guider . model_options [ " transformer_options " ] [ " easycache " ] = guider . model_options [ " transformer_options " ] [ " easycache " ] . clone ( ) . prepare_timesteps ( guider . model_patcher . model . model_sampling )
easycache : Union [ EasyCacheHolder , LazyCacheHolder ] = guider . model_options [ ' transformer_options ' ] [ ' easycache ' ]
logging . info ( f " { easycache . name } enabled - threshold: { easycache . reuse_threshold } , start_percent: { easycache . start_percent } , end_percent: { easycache . end_percent } " )
return executor ( * args , * * kwargs )
finally :
easycache = guider . model_options [ ' transformer_options ' ] [ ' easycache ' ]
output_change_rates = easycache . output_change_rates
approx_output_change_rates = easycache . approx_output_change_rates
if easycache . verbose :
logging . info ( f " { easycache . name } [verbose] - output_change_rates { len ( output_change_rates ) } : { output_change_rates } " )
logging . info ( f " { easycache . name } [verbose] - approx_output_change_rates { len ( approx_output_change_rates ) } : { approx_output_change_rates } " )
total_steps = len ( args [ 3 ] ) - 1
2025-09-08 12:07:04 -07:00
# catch division by zero for log statement; sucks to crash after all sampling is done
try :
speedup = total_steps / ( total_steps - easycache . total_steps_skipped )
except ZeroDivisionError :
speedup = 1.0
logging . info ( f " { easycache . name } - skipped { easycache . total_steps_skipped } / { total_steps } steps ( { speedup : .2f } x speedup). " )
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
easycache . reset ( )
guider . model_options = orig_model_options
class EasyCacheHolder :
2025-11-18 17:00:21 +02:00
def __init__ ( self , reuse_threshold : float , start_percent : float , end_percent : float , subsample_factor : int , offload_cache_diff : bool , verbose : bool = False , output_channels : int = None ) :
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
self . name = " EasyCache "
self . reuse_threshold = reuse_threshold
self . start_percent = start_percent
self . end_percent = end_percent
self . subsample_factor = subsample_factor
self . offload_cache_diff = offload_cache_diff
self . verbose = verbose
# timestep values
self . start_t = 0.0
self . end_t = 0.0
# control values
self . relative_transformation_rate : float = None
self . cumulative_change_rate = 0.0
self . initial_step = True
self . skip_current_step = False
# cache values
self . first_cond_uuid = None
self . x_prev_subsampled : torch . Tensor = None
self . output_prev_subsampled : torch . Tensor = None
self . output_prev_norm : torch . Tensor = None
self . uuid_cache_diffs : dict [ UUID , torch . Tensor ] = { }
2026-02-06 07:43:09 +02:00
self . uuid_cache_diffs_audio : dict [ UUID , torch . Tensor ] = { }
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
self . output_change_rates = [ ]
self . approx_output_change_rates = [ ]
self . total_steps_skipped = 0
# how to deal with mismatched dims
self . allow_mismatch = True
self . cut_from_start = True
2025-08-24 13:29:49 -06:00
self . state_metadata = None
2025-11-18 17:00:21 +02:00
self . output_channels = output_channels
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
def is_past_end_timestep ( self , timestep : float ) - > bool :
return not ( timestep [ 0 ] > self . end_t ) . item ( )
def should_do_easycache ( self , timestep : float ) - > bool :
return ( timestep [ 0 ] < = self . start_t ) . item ( )
def has_x_prev_subsampled ( self ) - > bool :
return self . x_prev_subsampled is not None
def has_output_prev_subsampled ( self ) - > bool :
return self . output_prev_subsampled is not None
def has_output_prev_norm ( self ) - > bool :
return self . output_prev_norm is not None
def has_relative_transformation_rate ( self ) - > bool :
return self . relative_transformation_rate is not None
def prepare_timesteps ( self , model_sampling ) :
self . start_t = model_sampling . percent_to_sigma ( self . start_percent )
self . end_t = model_sampling . percent_to_sigma ( self . end_percent )
return self
def subsample ( self , x : torch . Tensor , uuids : list [ UUID ] , clone : bool = True ) - > torch . Tensor :
batch_offset = x . shape [ 0 ] / / len ( uuids )
uuid_idx = uuids . index ( self . first_cond_uuid )
if self . subsample_factor > 1 :
to_return = x [ uuid_idx * batch_offset : ( uuid_idx + 1 ) * batch_offset , . . . , : : self . subsample_factor , : : self . subsample_factor ]
if clone :
return to_return . clone ( )
return to_return
to_return = x [ uuid_idx * batch_offset : ( uuid_idx + 1 ) * batch_offset , . . . ]
if clone :
return to_return . clone ( )
return to_return
2026-01-21 20:01:35 -08:00
def can_apply_cache_diff ( self , uuids : list [ UUID ] ) - > bool :
return all ( uuid in self . uuid_cache_diffs for uuid in uuids )
2026-02-06 07:43:09 +02:00
def apply_cache_diff ( self , x : torch . Tensor , uuids : list [ UUID ] , is_audio : bool = False ) :
if self . first_cond_uuid in uuids and not is_audio :
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
self . total_steps_skipped + = 1
2026-02-06 07:43:09 +02:00
cache_diffs = self . uuid_cache_diffs_audio if is_audio else self . uuid_cache_diffs
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
batch_offset = x . shape [ 0 ] / / len ( uuids )
for i , uuid in enumerate ( uuids ) :
2025-10-16 21:39:37 -07:00
# slice out only what is relevant to this cond
batch_slice = [ slice ( i * batch_offset , ( i + 1 ) * batch_offset ) ]
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
# if cached dims don't match x dims, cut off excess and hope for the best (cosmos world2video)
2026-02-06 07:43:09 +02:00
if x . shape [ 1 : ] != cache_diffs [ uuid ] . shape [ 1 : ] :
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
if not self . allow_mismatch :
raise ValueError ( f " Cached dims { self . uuid_cache_diffs [ uuid ] . shape } don ' t match x dims { x . shape } - this is no good " )
slicing = [ ]
skip_this_dim = True
2026-02-06 07:43:09 +02:00
for dim_u , dim_x in zip ( cache_diffs [ uuid ] . shape , x . shape ) :
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
if skip_this_dim :
skip_this_dim = False
continue
if dim_u != dim_x :
if self . cut_from_start :
slicing . append ( slice ( dim_x - dim_u , None ) )
else :
slicing . append ( slice ( None , dim_u ) )
else :
slicing . append ( slice ( None ) )
2025-10-16 21:39:37 -07:00
batch_slice = batch_slice + slicing
2026-02-06 07:43:09 +02:00
x [ tuple ( batch_slice ) ] + = cache_diffs [ uuid ] . to ( x . device )
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
return x
2026-02-06 07:43:09 +02:00
def update_cache_diff ( self , output : torch . Tensor , x : torch . Tensor , uuids : list [ UUID ] , is_audio : bool = False ) :
cache_diffs = self . uuid_cache_diffs_audio if is_audio else self . uuid_cache_diffs
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
# if output dims don't match x dims, cut off excess and hope for the best (cosmos world2video)
if output . shape [ 1 : ] != x . shape [ 1 : ] :
if not self . allow_mismatch :
raise ValueError ( f " Output dims { output . shape } don ' t match x dims { x . shape } - this is no good " )
slicing = [ ]
skip_dim = True
for dim_o , dim_x in zip ( output . shape , x . shape ) :
if not skip_dim and dim_o != dim_x :
if self . cut_from_start :
slicing . append ( slice ( dim_x - dim_o , None ) )
else :
slicing . append ( slice ( None , dim_o ) )
else :
slicing . append ( slice ( None ) )
skip_dim = False
2025-11-18 17:00:21 +02:00
x = x [ tuple ( slicing ) ]
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
diff = output - x
batch_offset = diff . shape [ 0 ] / / len ( uuids )
for i , uuid in enumerate ( uuids ) :
2026-02-06 07:43:09 +02:00
cache_diffs [ uuid ] = diff [ i * batch_offset : ( i + 1 ) * batch_offset , . . . ]
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
def has_first_cond_uuid ( self , uuids : list [ UUID ] ) - > bool :
return self . first_cond_uuid in uuids
2025-08-24 13:29:49 -06:00
def check_metadata ( self , x : torch . Tensor ) - > bool :
metadata = ( x . device , x . dtype , x . shape [ 1 : ] )
if self . state_metadata is None :
self . state_metadata = metadata
return True
if metadata == self . state_metadata :
return True
logging . warn ( f " { self . name } - Tensor shape, dtype or device changed, resetting state " )
self . reset ( )
return False
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
def reset ( self ) :
self . relative_transformation_rate = 0.0
self . cumulative_change_rate = 0.0
self . initial_step = True
self . skip_current_step = False
self . output_change_rates = [ ]
self . first_cond_uuid = None
del self . x_prev_subsampled
self . x_prev_subsampled = None
del self . output_prev_subsampled
self . output_prev_subsampled = None
del self . output_prev_norm
self . output_prev_norm = None
del self . uuid_cache_diffs
self . uuid_cache_diffs = { }
2026-02-06 07:43:09 +02:00
del self . uuid_cache_diffs_audio
self . uuid_cache_diffs_audio = { }
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
self . total_steps_skipped = 0
2025-08-24 13:29:49 -06:00
self . state_metadata = None
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
return self
def clone ( self ) :
2025-11-18 17:00:21 +02:00
return EasyCacheHolder ( self . reuse_threshold , self . start_percent , self . end_percent , self . subsample_factor , self . offload_cache_diff , self . verbose , output_channels = self . output_channels )
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
class EasyCacheNode ( io . ComfyNode ) :
@classmethod
def define_schema ( cls ) - > io . Schema :
return io . Schema (
node_id = " EasyCache " ,
display_name = " EasyCache " ,
description = " Native EasyCache implementation. " ,
category = " advanced/debug/model " ,
is_experimental = True ,
inputs = [
io . Model . Input ( " model " , tooltip = " The model to add EasyCache to. " ) ,
feat: mark 429 widgets as advanced for collapsible UI (#12197)
* feat: mark 429 widgets as advanced for collapsible UI
Mark widgets as advanced across core, comfy_extras, and comfy_api_nodes
to support the new collapsible advanced inputs section in the frontend.
Changes:
- 267 advanced markers in comfy_extras/
- 162 advanced markers in comfy_api_nodes/
- All files pass python3 -m py_compile verification
Widgets marked advanced (hidden by default):
- Scheduler internals: sigma_max, sigma_min, rho, mu, beta, alpha
- Sampler internals: eta, s_noise, order, rtol, atol, h_init, pcoeff, etc.
- Memory optimization: tile_size, overlap, temporal_size, temporal_overlap
- Pipeline controls: add_noise, start_at_step, end_at_step
- Timing controls: start_percent, end_percent
- Layer selection: stop_at_clip_layer, layers, block_number
- Video encoding: codec, crf, format
- Device/dtype: device, noise_device, dtype, weight_dtype
Widgets kept basic (always visible):
- Core params: strength, steps, cfg, denoise, seed, width, height
- Model selectors: ckpt_name, lora_name, vae_name, sampler_name
- Common controls: upscale_method, crop, batch_size, fps, opacity
Related: frontend PR #11939
Amp-Thread-ID: https://ampcode.com/threads/T-019c1734-6b61-702e-b333-f02c399963fc
* fix: remove advanced=True from DynamicCombo.Input (unsupported)
Amp-Thread-ID: https://ampcode.com/threads/T-019c1734-6b61-702e-b333-f02c399963fc
* fix: address review - un-mark model merge, video, image, and training node widgets as advanced
Per comfyanonymous review:
- Model merge arguments should not be advanced (all 14 model-specific merge classes)
- SaveAnimatedWEBP lossless/quality/method should not be advanced
- SaveWEBM/SaveVideo codec/crf/format should not be advanced
- TrainLoraNode options should not be advanced (7 inputs)
Amp-Thread-ID: https://ampcode.com/threads/T-019c322b-a3a8-71b7-9962-d44573ca6352
* fix: un-mark batch_size and webcam width/height as advanced (should stay basic)
Amp-Thread-ID: https://ampcode.com/threads/T-019c3236-1417-74aa-82a3-bcb365fbe9d1
---------
Co-authored-by: Jedrzej Kosinski <kosinkadink1@gmail.com>
2026-02-19 19:20:02 -08:00
io . Float . Input ( " reuse_threshold " , min = 0.0 , default = 0.2 , max = 3.0 , step = 0.01 , tooltip = " The threshold for reusing cached steps. " , advanced = True ) ,
io . Float . Input ( " start_percent " , min = 0.0 , default = 0.15 , max = 1.0 , step = 0.01 , tooltip = " The relative sampling step to begin use of EasyCache. " , advanced = True ) ,
io . Float . Input ( " end_percent " , min = 0.0 , default = 0.95 , max = 1.0 , step = 0.01 , tooltip = " The relative sampling step to end use of EasyCache. " , advanced = True ) ,
io . Boolean . Input ( " verbose " , default = False , tooltip = " Whether to log verbose information. " , advanced = True ) ,
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
] ,
outputs = [
io . Model . Output ( tooltip = " The model with EasyCache. " ) ,
] ,
)
@classmethod
def execute ( cls , model : io . Model . Type , reuse_threshold : float , start_percent : float , end_percent : float , verbose : bool ) - > io . NodeOutput :
model = model . clone ( )
2025-11-18 17:00:21 +02:00
model . model_options [ " transformer_options " ] [ " easycache " ] = EasyCacheHolder ( reuse_threshold , start_percent , end_percent , subsample_factor = 8 , offload_cache_diff = False , verbose = verbose , output_channels = model . model . latent_format . latent_channels )
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
model . add_wrapper_with_key ( comfy . patcher_extension . WrappersMP . OUTER_SAMPLE , " easycache " , easycache_sample_wrapper )
model . add_wrapper_with_key ( comfy . patcher_extension . WrappersMP . CALC_COND_BATCH , " easycache " , easycache_calc_cond_batch_wrapper )
model . add_wrapper_with_key ( comfy . patcher_extension . WrappersMP . DIFFUSION_MODEL , " easycache " , easycache_forward_wrapper )
return io . NodeOutput ( model )
class LazyCacheHolder :
2025-11-18 17:00:21 +02:00
def __init__ ( self , reuse_threshold : float , start_percent : float , end_percent : float , subsample_factor : int , offload_cache_diff : bool , verbose : bool = False , output_channels : int = None ) :
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
self . name = " LazyCache "
self . reuse_threshold = reuse_threshold
self . start_percent = start_percent
self . end_percent = end_percent
self . subsample_factor = subsample_factor
self . offload_cache_diff = offload_cache_diff
self . verbose = verbose
# timestep values
self . start_t = 0.0
self . end_t = 0.0
# control values
self . relative_transformation_rate : float = None
self . cumulative_change_rate = 0.0
self . initial_step = True
# cache values
self . x_prev_subsampled : torch . Tensor = None
self . output_prev_subsampled : torch . Tensor = None
self . output_prev_norm : torch . Tensor = None
self . cache_diff : torch . Tensor = None
self . output_change_rates = [ ]
self . approx_output_change_rates = [ ]
self . total_steps_skipped = 0
2025-08-24 13:29:49 -06:00
self . state_metadata = None
2025-11-18 17:00:21 +02:00
self . output_channels = output_channels
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
def has_cache_diff ( self ) - > bool :
return self . cache_diff is not None
def is_past_end_timestep ( self , timestep : float ) - > bool :
return not ( timestep [ 0 ] > self . end_t ) . item ( )
def should_do_easycache ( self , timestep : float ) - > bool :
return ( timestep [ 0 ] < = self . start_t ) . item ( )
def has_x_prev_subsampled ( self ) - > bool :
return self . x_prev_subsampled is not None
def has_output_prev_subsampled ( self ) - > bool :
return self . output_prev_subsampled is not None
def has_output_prev_norm ( self ) - > bool :
return self . output_prev_norm is not None
def has_relative_transformation_rate ( self ) - > bool :
return self . relative_transformation_rate is not None
def prepare_timesteps ( self , model_sampling ) :
self . start_t = model_sampling . percent_to_sigma ( self . start_percent )
self . end_t = model_sampling . percent_to_sigma ( self . end_percent )
return self
def subsample ( self , x : torch . Tensor , clone : bool = True ) - > torch . Tensor :
if self . subsample_factor > 1 :
to_return = x [ . . . , : : self . subsample_factor , : : self . subsample_factor ]
if clone :
return to_return . clone ( )
return to_return
if clone :
return x . clone ( )
return x
def apply_cache_diff ( self , x : torch . Tensor ) :
self . total_steps_skipped + = 1
return x + self . cache_diff . to ( x . device )
def update_cache_diff ( self , output : torch . Tensor , x : torch . Tensor ) :
self . cache_diff = output - x
2025-08-24 13:29:49 -06:00
def check_metadata ( self , x : torch . Tensor ) - > bool :
metadata = ( x . device , x . dtype , x . shape )
if self . state_metadata is None :
self . state_metadata = metadata
return True
if metadata == self . state_metadata :
return True
logging . warn ( f " { self . name } - Tensor shape, dtype or device changed, resetting state " )
self . reset ( )
return False
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
def reset ( self ) :
self . relative_transformation_rate = 0.0
self . cumulative_change_rate = 0.0
self . initial_step = True
self . output_change_rates = [ ]
self . approx_output_change_rates = [ ]
del self . cache_diff
self . cache_diff = None
2025-08-24 13:29:49 -06:00
del self . x_prev_subsampled
self . x_prev_subsampled = None
del self . output_prev_subsampled
self . output_prev_subsampled = None
del self . output_prev_norm
self . output_prev_norm = None
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
self . total_steps_skipped = 0
2025-08-24 13:29:49 -06:00
self . state_metadata = None
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
return self
def clone ( self ) :
2025-11-18 17:00:21 +02:00
return LazyCacheHolder ( self . reuse_threshold , self . start_percent , self . end_percent , self . subsample_factor , self . offload_cache_diff , self . verbose , output_channels = self . output_channels )
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
class LazyCacheNode ( io . ComfyNode ) :
@classmethod
def define_schema ( cls ) - > io . Schema :
return io . Schema (
node_id = " LazyCache " ,
display_name = " LazyCache " ,
description = " A homebrew version of EasyCache - even ' easier ' version of EasyCache to implement. Overall works worse than EasyCache, but better in some rare cases AND universal compatibility with everything in ComfyUI. " ,
category = " advanced/debug/model " ,
is_experimental = True ,
inputs = [
io . Model . Input ( " model " , tooltip = " The model to add LazyCache to. " ) ,
feat: mark 429 widgets as advanced for collapsible UI (#12197)
* feat: mark 429 widgets as advanced for collapsible UI
Mark widgets as advanced across core, comfy_extras, and comfy_api_nodes
to support the new collapsible advanced inputs section in the frontend.
Changes:
- 267 advanced markers in comfy_extras/
- 162 advanced markers in comfy_api_nodes/
- All files pass python3 -m py_compile verification
Widgets marked advanced (hidden by default):
- Scheduler internals: sigma_max, sigma_min, rho, mu, beta, alpha
- Sampler internals: eta, s_noise, order, rtol, atol, h_init, pcoeff, etc.
- Memory optimization: tile_size, overlap, temporal_size, temporal_overlap
- Pipeline controls: add_noise, start_at_step, end_at_step
- Timing controls: start_percent, end_percent
- Layer selection: stop_at_clip_layer, layers, block_number
- Video encoding: codec, crf, format
- Device/dtype: device, noise_device, dtype, weight_dtype
Widgets kept basic (always visible):
- Core params: strength, steps, cfg, denoise, seed, width, height
- Model selectors: ckpt_name, lora_name, vae_name, sampler_name
- Common controls: upscale_method, crop, batch_size, fps, opacity
Related: frontend PR #11939
Amp-Thread-ID: https://ampcode.com/threads/T-019c1734-6b61-702e-b333-f02c399963fc
* fix: remove advanced=True from DynamicCombo.Input (unsupported)
Amp-Thread-ID: https://ampcode.com/threads/T-019c1734-6b61-702e-b333-f02c399963fc
* fix: address review - un-mark model merge, video, image, and training node widgets as advanced
Per comfyanonymous review:
- Model merge arguments should not be advanced (all 14 model-specific merge classes)
- SaveAnimatedWEBP lossless/quality/method should not be advanced
- SaveWEBM/SaveVideo codec/crf/format should not be advanced
- TrainLoraNode options should not be advanced (7 inputs)
Amp-Thread-ID: https://ampcode.com/threads/T-019c322b-a3a8-71b7-9962-d44573ca6352
* fix: un-mark batch_size and webcam width/height as advanced (should stay basic)
Amp-Thread-ID: https://ampcode.com/threads/T-019c3236-1417-74aa-82a3-bcb365fbe9d1
---------
Co-authored-by: Jedrzej Kosinski <kosinkadink1@gmail.com>
2026-02-19 19:20:02 -08:00
io . Float . Input ( " reuse_threshold " , min = 0.0 , default = 0.2 , max = 3.0 , step = 0.01 , tooltip = " The threshold for reusing cached steps. " , advanced = True ) ,
io . Float . Input ( " start_percent " , min = 0.0 , default = 0.15 , max = 1.0 , step = 0.01 , tooltip = " The relative sampling step to begin use of LazyCache. " , advanced = True ) ,
io . Float . Input ( " end_percent " , min = 0.0 , default = 0.95 , max = 1.0 , step = 0.01 , tooltip = " The relative sampling step to end use of LazyCache. " , advanced = True ) ,
io . Boolean . Input ( " verbose " , default = False , tooltip = " Whether to log verbose information. " , advanced = True ) ,
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
] ,
outputs = [
io . Model . Output ( tooltip = " The model with LazyCache. " ) ,
] ,
)
@classmethod
def execute ( cls , model : io . Model . Type , reuse_threshold : float , start_percent : float , end_percent : float , verbose : bool ) - > io . NodeOutput :
model = model . clone ( )
2025-11-18 17:00:21 +02:00
model . model_options [ " transformer_options " ] [ " easycache " ] = LazyCacheHolder ( reuse_threshold , start_percent , end_percent , subsample_factor = 8 , offload_cache_diff = False , verbose = verbose , output_channels = model . model . latent_format . latent_channels )
Implement EasyCache and Invent LazyCache (#9496)
* Attempting a universal implementation of EasyCache, starting with flux as test; I screwed up the math a bit, but when I set it just right it works.
* Fixed math to make threshold work as expected, refactored code to use EasyCacheHolder instead of a dict wrapped by object
* Use sigmas from transformer_options instead of timesteps to be compatible with a greater amount of models, make end_percent work
* Make log statement when not skipping useful, preparing for per-cond caching
* Added DIFFUSION_MODEL wrapper around forward function for wan model
* Add subsampling for heuristic inputs
* Add subsampling to output_prev (output_prev_subsampled now)
* Properly consider conds in EasyCache logic
* Created SuperEasyCache to test what happens if caching and reuse is moved outside the scope of conds, added PREDICT_NOISE wrapper to facilitate this test
* Change max reuse_threshold to 3.0
* Mark EasyCache/SuperEasyCache as experimental (beta)
* Make Lumina2 compatible with EasyCache
* Add EasyCache support for Qwen Image
* Fix missing comma, curse you Cursor
* Add EasyCache support to AceStep
* Add EasyCache support to Chroma
* Added EasyCache support to Cosmos Predict t2i
* Make EasyCache not crash with Cosmos Predict ImagToVideo latents, but does not work well at all
* Add EasyCache support to hidream
* Added EasyCache support to hunyuan video
* Added EasyCache support to hunyuan3d
* Added EasyCache support to LTXV (not very good, but does not crash)
* Implemented EasyCache for aura_flow
* Renamed SuperEasyCache to LazyCache, hardcoded subsample_factor to 8 on nodes
* Eatra logging when verbose is true for EasyCache
2025-08-22 19:41:08 -07:00
model . add_wrapper_with_key ( comfy . patcher_extension . WrappersMP . OUTER_SAMPLE , " lazycache " , easycache_sample_wrapper )
model . add_wrapper_with_key ( comfy . patcher_extension . WrappersMP . PREDICT_NOISE , " lazycache " , lazycache_predict_noise_wrapper )
return io . NodeOutput ( model )
class EasyCacheExtension ( ComfyExtension ) :
async def get_node_list ( self ) - > list [ type [ io . ComfyNode ] ] :
return [
EasyCacheNode ,
LazyCacheNode ,
]
def comfy_entrypoint ( ) :
return EasyCacheExtension ( )