diffusion cache: floor the strength-scaled step count like diffusers

effective_denoise_steps computed ceil(steps * strength) (steps - int(steps - steps*strength)),
but diffusers get_timesteps denoises init_timestep = min(int(num_inference_steps * strength),
num_inference_steps), i.e. the floored product. The two differ by one whenever the product is
fractional, and that flips the auto FBCache decision in the (19, 20) band: a strength-0.7
28-step img2img denoises int(19.6) = 19 real steps (below FBCACHE_MIN_STEPS = 20) but the old
formula returned 20 and engaged FBCache on that short trajectory, exactly the quality hit the
auto policy exists to avoid. Return min(int(steps * strength), steps) to match diffusers, and
fix the two tests that replayed the old formula.

Also honor _default_threads' documented fallback: (os.cpu_count() or 8) // 2 yields 4 when the
count is unknown, contradicting the docstring's 'falls back to 8'. Return 8 in that case.
This commit is contained in:
Daniel Han 2026-07-06 09:59:54 +00:00
commit 6e5d11a0a7
3 changed files with 15 additions and 14 deletions

View file

@ -192,19 +192,19 @@ def test_effective_steps_txt2img_is_full_count():
def test_effective_steps_low_strength_shrinks_below_the_bar():
# A 28-step upscale at strength 0.35 denoises ~10 steps (diffusers get_timesteps),
# which is below FBCACHE_MIN_STEPS -> the auto policy must NOT engage FBCache there.
# A 28-step upscale at strength 0.35 denoises int(9.8) = 9 steps (diffusers get_timesteps
# floors the product), which is below FBCACHE_MIN_STEPS -> the auto policy must NOT engage
# FBCache there.
eff = effective_denoise_steps(28, 0.35)
assert eff == 10
assert eff == 9
assert eff < FBCACHE_MIN_STEPS
def test_effective_steps_matches_diffusers_get_timesteps():
# Mirror diffusers exactly: num_inference_steps - int(num_inference_steps -
# min(num_inference_steps * strength, num_inference_steps)).
# Mirror diffusers exactly: it denoises init_timestep = min(int(num_inference_steps *
# strength), num_inference_steps) steps (the product is floored, not rounded).
for steps, strength in [(28, 0.35), (28, 0.8), (50, 0.5), (20, 0.99), (30, 0.1)]:
init = min(steps * strength, steps)
expected = max(1, steps - int(max(steps - init, 0)))
expected = max(1, min(int(steps * strength), steps))
assert effective_denoise_steps(steps, strength) == expected