Division by 0 bug when only one denoising step
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 72/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Tranquilla
- Stack tecnologico
- python, pytorch
- Ambito
- machine-learning
Direzione di ricerca
Inizia da diffusers/src/diffusers/schedulers/scheduling_flow_match_euler_discrete.py, in particolare da stretch_shift_to_terminal, set_timesteps e index_for_timestep; usa xfuser/model_executor/models/runner_models/ltx.py per riprodurre il percorso a un passaggio. Esegui il comando LTX-2.3 riportato con num_inference_steps=1 e verifica che lo scheduler produca una pianificazione valida senza valori NaN né un IndexError, mentre il comportamento a più passaggi rimane invariato.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Describe the bug
When run_timed_pipe is called: https://github.com/xdit-project/xDiT/blob/9705ed0d7509537b4d2697f27c089bab5c6e96a3/xfuser/model_executor/models/runner_models/ltx.py#L198, an array sigmas is created that represents the denoising steps. 1.0 indicates pure noise and 0.0 indicates a clean output. sigmas always starts with 1.0. sigmas = np.linspace(1.0, 1 / num_inference_steps, num_inference_steps): https://github.com/xdit-project/xDiT/blob/9705ed0d7509537b4d2697f27c089bab5c6e96a3/xfuser/model_executor/pipelines/pipeline_flux.py#L277.
num_inference_steps is a parameter in xDiT that controls the number of denoising steps.
- num_inference_steps=2: sigmas = [1.0, 0.5] - two points from full noise to half noise
- num_inference_steps=1: sigmas = [1.0] — a single point at full noise
Dynamic time shifting is applied to sigmas via time_shift function: https://github.com/huggingface/diffusers/blob/9c6a68c32b3b2a64db91800b624d33cec6e25ab8/src/diffusers/schedulers/scheduling_flow_match_euler_discrete.py#L241
After time_shift, sigmas is compressed and stretch_shift_to_terminal linearly rescales the schedule in completion space so the last sigma lands at shift_terminal (often 0.1).
The issue is that stretch_shift_to_terminal assumes there to be multiple denoising steps and sets sigmas to be [nan] when num_inference_steps = 1:
def stretch_shift_to_terminal(self, t):
one_minus_z = 1 - t # 1 - 1 = 0
scale_factor = one_minus_z[-1] / (1 - self.config.shift_terminal) -> # 0 / (1 - 0.1) = 0
stretched_t = 1 - (one_minus_z / scale_factor) # 1 - (0 / 0). Division by 0 -> nan
return stretched_t -> nan
When sigmas is indexed: https://github.com/huggingface/diffusers/blob/9c6a68c32b3b2a64db91800b624d33cec6e25ab8/src/diffusers/schedulers/scheduling_flow_match_euler_discrete.py#L413, since it contains nan, it errors.
The starting point in a diffusion pipeline is always pure noise and should be 1.0. If there's only one denoising step the denoising should go from 1.0 to 0.0 and stretch_shift_to_terminal should be skipped since there's nothing to shift.
if self.config.shift_terminal:
sigmas = self.stretch_shift_to_terminal(sigmas)
should be changed to
if self.config.shift_terminal and len(sigmas) > 1:
sigmas = self.stretch_shift_to_terminal(sigmas)
Reproduction
Modify https://github.com/xdit-project/xDiT/blob/9705ed0d7509537b4d2697f27c089bab5c6e96a3/xfuser/model_executor/models/runner_models/ltx.py#L197 to set compile_args["num_inference_steps"] = 1. For context, I am working on a PR to xDiT that involves running _run_timed_pipe once with compile_args["num_inference_steps"] = 1 to profile the CUDA graph capture phase.
Run:
xdit \
--model "LTX-2.3" \
--seed "42" \
--prompt "a cat" \
--height "256" \
--width "256" \
--num_inference_steps "4" \
--max_sequence_length "512" \
--warmup_calls "0" \
--ulysses_degree "1" \
--guidance_scale "4" \
--num_iterations "4" \
--attention_backend "aiter" \
--input_images "/app/data/flux_cat.png" \
--output_directory "${XDIT_RUN_DIR}" \
--use_torch_compile \
--profile --profile_wait 1 --profile_warmup 2 --profile_active 1
Logs
[rank0]: Traceback (most recent call last):
[rank0]: File "<frozen runpy>", line 198, in _run_module_as_main
[rank0]: File "<frozen runpy>", line 88, in _run_code
[rank0]: File "/app/xDiT/xfuser/runner.py", line 123, in <module>
[rank0]: runner.initialize(input_args)
[rank0]: File "/app/xDiT/xfuser/runner.py", line 61, in initialize
[rank0]: self.model.initialize(input_args)
[rank0]: File "/app/xDiT/xfuser/model_executor/models/runner_models/base_model.py", line 273, in initialize
[rank0]: self._compile_model(compile_input_args)
[rank0]: File "/app/xDiT/xfuser/model_executor/models/runner_models/ltx.py", line 194, in _compile_model
[rank0]: self._run_compile_warmup(compile_args)
[rank0]: File "/app/xDiT/xfuser/model_executor/models/runner_models/base_model.py", line 645, in _run_compile_warmup
[rank0]: self._run_timed_pipe(compile_args)
[rank0]: File "/app/xDiT/xfuser/model_executor/models/runner_models/base_model.py", line 614, in _run_timed_pipe
[rank0]: out = self._run_pipe(input_args)
[rank0]: File "/app/xDiT/xfuser/model_executor/models/runner_models/ltx.py", line 127, in _run_pipe
[rank0]: video_latent, audio_latent = self.pipe(
[rank0]: File "/venv/lib/python3.12/site-packages/torch/utils/_contextlib.py", line 120, in decorate_context
[rank0]: return func(*args, **kwargs)
[rank0]: File "/app/external/diffusers/src/diffusers/pipelines/ltx2/pipeline_ltx2.py", line 1402, in __call__
[rank0]: latents = self.scheduler.step(noise_pred_video, t, latents, return_dict=False)[0]
[rank0]: File "/app/external/diffusers/src/diffusers/schedulers/scheduling_flow_match_euler_discrete.py", line 483, in step
[rank0]: self._init_step_index(timestep)
[rank0]: File "/app/external/diffusers/src/diffusers/schedulers/scheduling_flow_match_euler_discrete.py", line 421, in _init_step_index
[rank0]: self._step_index = self.index_for_timestep(timestep)
[rank0]: File "/app/external/diffusers/src/diffusers/schedulers/scheduling_flow_match_euler_discrete.py", line 415, in index_for_timestep
[rank0]: return indices[pos].item()
[rank0]: ~~~~~~~^^^^^
[rank0]: IndexError: index 0 is out of bounds for dimension 0 with size 0
System Info
- 🤗 Diffusers version: 0.38.0.dev0
- Platform: Linux-6.8.0-31-generic-x86_64-with-glibc2.39
- Running on Google Colab?: No
- Python version: 3.12.3
- PyTorch version (GPU?): 2.9.1+gitff65f5b (True)
- Flax version (CPU?/GPU?/TPU?): not installed (NA)
- Jax version: not installed
- JaxLib version: not installed
- Huggingface_hub version: 1.20.1
- Transformers version: 5.5.4
- Accelerate version: 1.14.0
- PEFT version: 0.19.1
- Bitsandbytes version: not installed
- Safetensors version: 0.8.0
- xFormers version: not installed
- Accelerator: NA
- Using GPU in script?:
- Using distributed or parallel set-up in script?:
Who can help?
No response
- Lingua principale
- Python
- Stelle
- 34.6k
- Fork
- 7.3k
- Merge medio
- 3g 16h
- PR unite (30g)
- 74
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di huggingface/diffusers
-
bug needs-env-info pipelines
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
huggingface/diffusers#14794 ·
-
bug needs-code-example needs-env-info pipelines
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 86/100
huggingface/diffusers#14780 · 1 commento ·
-
bug pipelines
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
huggingface/diffusers#14769 · 1 commento ·
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
huggingface/diffusers#14639 ·
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
huggingface/diffusers#14616 ·
Tutte le issue di huggingface/diffusers
Issue simili
-
documentation help wanted
Difficoltà 2/5 1-3 ore Idoneità per principianti 90/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 90/100
simonw/sqlite-utils#872 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100