Open
Description
Right now we are adding the schedulers, but it is difficult to work with since swapping the scheduler doesn't work well. This also slows down testing and evaluation of the schedulers, as a separate script needs to be made each time to test the samplers. I also was implementing these into an application and swapping the schedulers wasn't working (due to different types at runtime).
I experimented some in adding a trait, so we can use impl Scheduler
. Came up with the following, but causes some points of contention.
- steps need a
&mut self
for some schedulers - steps needs a timestep of different number types (
f64
andusize
) currently - add_noise doesn't have a noise input on each one
- timesteps returns a slice of
usize
orf64
(or maybe other ones?)
pub trait Scheduler {
fn step<T: SomeTraitThatWouldTakef64AndUsize>(&mut self, model_output: &Tensor, timestep: T, sample: &Tensor) -> Tensor;
fn timesteps(&self) -> &[usize];
fn add_noise(&self, original_samples: &Tensor, noise: Tensor, timestep: usize) -> Tensor;
fn init_noise_sigma(&self) -> f64;
fn scale_model_input(&self, sample: Tensor, timestep: usize) -> Tensor;
}
And then I could do the following (I'm still learning traits):
sample<T: Scheduler>(
...,
mut scheduler: T
)
And/or we could also do a Scheduler enum.
enum SamplerScheduler {
Dpmpp2m(dpmsolver_multistep::DPMSolverMultistepScheduler),
Dpmpp2s(dpmsolver_singlestep::DPMSolverSinglestepScheduler),
Ddim(ddim::DDIMScheduler),
Ddpm(ddpm::DDPMScheduler),
EulerDiscrete(euler_discrete::EulerDiscreteScheduler),
}
I'm not 100% sure what's the best approach.
Metadata
Metadata
Assignees
Labels
No labels