Skip to content

scheduler leaky abstractions in pipelines #336

Closed
@keturn

Description

@keturn

Excited by the opportunities that Stable Diffusion has made for use with consumer hardware, I've started working with the code. I was looking to get an idea of what I'd need to do for something like #277 and studying the StableDiffusionPipeline class.

I'm concerned by the use of isinstance(self.scheduler, LMSDiscreteScheduler). If you can't implement a new Scheduler without meddling with the internal implementation of the Pipeline, that points to some breakdown in the API design. We don't want growing if isintance trees that grow with each New Scheduler PR.

It also introduces an ordering dependency between components that weren't otherwise entangled:

self.scheduler.set_timesteps(num_inference_steps, **extra_set_kwargs)
# if we use LMSDiscreteScheduler, let's make sure latents are mulitplied by sigmas
if isinstance(self.scheduler, LMSDiscreteScheduler):
latents = latents * self.scheduler.sigmas[0]

It wasn't obvious to me at first glance, but scheduler.set_timesteps modifies scheduler.sigmas. So now when working with that code we have to remember that we have to do that scheduler initialization before we finish preparing the initial latents, whereas those were independent operations before.

Another worrying comment is this:

# prepare extra kwargs for the scheduler step, since not all schedulers have the same signature
# eta (η) is only used with the DDIMScheduler, it will be ignored for other schedulers.
# eta corresponds to η in DDIM paper: https://arxiv.org/abs/2010.02502
# and should be between [0, 1]
accepts_eta = "eta" in set(inspect.signature(self.scheduler.step).parameters.keys())

If "not all schedulers share the same signature," it's much harder to make and use Schedulers.

Suggestions

LMSDiscreteScheduler's step function seems to want the step number instead of the time. Options:

  1. Change the signature of Scheduler.step to always include the index as well as the time. (It's readily available and cheap to have on the stack.)
  2. Since LMS is linear (right there in the name!), could it take the usual timestep value and easily convert it back to its index value?

For DDIMScheduler's extra eta parameter:

The **kwargs on StableDiffusionPipeline.__call__ seems to be unused, and eta seems to be passed straight through to scheduler.step with no other interaction. We could take eta out of the formal parameter list and rename kwargs to extra_step_kwargs.

I haven't yet looked at other uses of Scheduler outside of this one pipeline, but those are my initial thoughts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions