Repository navigation
fix: keep at least one trimmed sigma in the hires refine schedule #2361
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -511,6 +511,12 @@ namespace sd::pipeline { | |
| // unlike img2img which trims from a fixed step count. | ||
| int scheduler_steps = static_cast<int>(effective_steps / hires.denoising_strength); | ||
| scheduler_steps = std::max(1, scheduler_steps); | ||
| // Truncation maps every denoising_strength in (n / (n + 1), 1) back to n scheduler steps, so the trim below drops | ||
| // no sigma at all and the second pass restarts from sigma_max, discarding the upscaled latent. Keep at least one | ||
| // trimmed sigma; denoising_strength = 1 is the intentional full-denoise case and must keep starting at sigma_max. | ||
| if (scheduler_steps <= effective_steps && hires.denoising_strength < 1.0f) { | ||
| scheduler_steps = effective_steps + 1; | ||
| } | ||
|
|
||
| scheduler_t scheduler = resolve_scheduler(sd, | ||
| sample_params.scheduler, | ||
|
|
@@ -523,8 +529,19 @@ namespace sd::pipeline { | |
| if (scheduler_steps_out != nullptr) { | ||
| *scheduler_steps_out = scheduler_steps; | ||
| } | ||
| return std::vector<float>(sigmas.begin() + std::max(0, scheduler_steps - effective_steps), | ||
| sigmas.end()); | ||
| std::vector<float> refine_sigmas(sigmas.begin() + std::max(0, scheduler_steps - effective_steps), | ||
| sigmas.end()); | ||
| // The trim always keeps a suffix, so the starting sigma depends on effective_steps alone. With effective_steps = 1 | ||
| // it is the last sigma before the terminal zero, which no scheduler_steps can raise. Report the under-refinement | ||
| // instead of silently returning a schedule that barely changes the upscaled latent. | ||
| if (refine_sigmas.size() > 1 && refine_sigmas.front() < hires.denoising_strength) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exclude valid full-denoise schedules from the under-refinement warning. With Skip intentional full denoising and restrict this warning to a scheduler-aware near-zero or degenerate start. Based on learnings, numeric thresholds must match the compared value’s runtime scale.
|
||
| LOG_WARN("hires refine starts at sigma %.4f over %d step(s), less than the requested denoising strength " | ||
| "%.2f; the upscaled latent will barely be refined (increase --hires-steps)", | ||
| refine_sigmas.front(), | ||
| effective_steps, | ||
| hires.denoising_strength); | ||
| } | ||
| return refine_sigmas; | ||
| } | ||
|
|
||
| } // namespace sd::pipeline | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep a positive starting sigma for one-step refinement.
With MingImageFlowDenoiser, discrete scheduling,
hires.steps=1, and strength0.7, this produces[1,0,0]. Trimming returns[0,0], so Euler skips refinement entirely. Select a positive starting sigma instead of the duplicated terminal zero. (raw.githubusercontent.com)Sefi sampling ignores the trimmed schedule from the hires helper.
With Sefi,
sample_sefi_eulerreads the cachedtex_sigmasandsem_sigmasmembers ofSefiFlowDenoiser. It does not use the trimmed vector that the hires helper returns. Forhires.steps=2and strength0.7, the cache holds untrimmed entries, so sampling starts at the first cached sigma and runs three updates. The refine pass can then restart from the full schedule instead of the trimmed suffix.This divergence exists before this PR. Any already-trimmed schedule on the Sefi path reaches the same untrimmed cache. The added step changes the trimmed length, but it does not create the mismatch. Fix the Sefi sampling path so that initialization, cached schedules, and timestep indexing use the same schedule. The exact correction needs the intended trim contract for
sem_sigmas/tex_sigmas, which the inspected source does not establish.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On Keep a positive starting sigma for one-step refinement:
Checked against both the source and a live run — the numbers differ per denoiser, but the direction of the finding is right.
With
--hires-steps 1 --hires-denoising-strength 0.7:MingImageFlowDenoiser1, 0, 00, 0— refine skippedMiniMaxH3ImageDenoiser1, 0.0119, 00.0119, 0— one step, effectively a no-opSo H3 is not skipped, but it is degenerate in a different way: 0.7 and 0.5 produce bit-identical video frames (md5
046d19ee…), i.e. the strength has no effect at all once there is a single step.The reason is one level deeper than this branch's change: the trim is always a suffix,
sigmas[scheduler_steps - effective_steps ...], so the starting sigma is a function ofeffective_stepsonly and is independent ofscheduler_steps. Foreffective_steps = 1it is always the last sigma before the terminal zero, and no step count can raise it. Pre-fix that configuration started atsigma_max(upscaler discarded); post-fix it starts near 0 (upscaler kept, but the pass barely moves). Picking a differentscheduler_stepscannot fix either of those, so I did not add heuristics to the step count — instead the helper now reports the under-refinement:Re-ran the matrix on
MiniMax-H3+ the 3D upscaler (320x320 -> 448x448, 6 frames, Euler/discrete). The warning fires only in the one-step case, and every schedule is unchanged from before this commit:Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On Sefi sampling ignores the trimmed schedule from the hires helper:
Confirmed in source, and agreed it is out of scope for this PR.
sample_sefi_euler()(src/runtime/denoiser.hpp:1839) iterates the cachedsefi->tex_sigmas/sefi->sem_sigmas. Those are filled bySefiFlowDenoiser::get_sigmas()(:1547) with alln + 1entries, and the call site (:3114) never passes the trimmed vector returned bymake_hires_sigma_schedule(). So the trim is dropped on the Sefi path — for this change and for any schedule that was already trimmed before it, as you noted.I would rather not guess the contract here either.
sem_sigmasandtex_sigmasare two parallel schedules driven by the same step index, withsemshifted ahead oftexbydelta_t; deciding what "trim" means for the pair (same number of dropped steps? drop on the sem axis and re-derive tex?) changes sampling behaviour for every Sefi run, not just hires. That needs a maintainer's call on the intended semantics plus a run with the Sefi model, so it should not ride along in a 6-line fix for the truncation bug — happy to file it as a separate issue if that is preferred.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Analysis chain
Script executed:
Length of output: 9195
Script executed:
Length of output: 21690
@farawaysoThanks for the source check and run. The warning makes the Ming[0, 0]case visible, but it does not make Euler perform the refinement. I’m not marking the finding as addressed.One correction: suffix trimming alone does not make the starting sigma independent of
scheduler_steps. For example,MiniMaxH3ImageDenoiser::get_sigmas()samples different grid positions for different step counts. The comment atsrc/pipeline/request.cppLine 534 should be narrower.You are interacting with an AI system.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Analysis chain
Script executed:
Length of output: 17999
@farawaysoYes, a separate issue is appropriate. The follow-up can establish how to trim both schedules and validate the result with a Sefi model.The Sefi finding remains valid, so I’m not marking it as addressed.
You are interacting with an AI system.