Skip to content

[draft] refactor DPMSolverMultistepScheduler using sigmas #4690

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

Closed
wants to merge 9 commits into from

Conversation

yiyixuxu
Copy link
Collaborator

@yiyixuxu yiyixuxu commented Aug 21, 2023

This PR refactor DPMSolverMultistepScheduler: update the computation to use sigmas.

currently, I only refactored "dpmsolver++" and "sde-dpmsolver++"
to-do left:

  • "dpmsolver++"
  • "sde-dpmsolver++"
  • "sde-dpmsolver"
  • "dpmsolver"

#4187

yiyixuxu and others added 6 commits July 21, 2023 03:52
@HuggingFaceDocBuilderDev
Copy link

HuggingFaceDocBuilderDev commented Aug 21, 2023

The documentation is not available anymore as the PR was closed or merged.

@yiyixuxu
Copy link
Collaborator Author

yiyixuxu commented Sep 9, 2023

@patrickvonplaten

Do we really need "sde-dpmsolver" and "dpmsolver" here?

We have so many options here, and I think that really confuses people. i.e. we have 4 algorithm_type, 2 solver_order, and 2 solver_type, so 16 combinations here 😅

Can we possibly trim it a little bit as I refactor it? From what I understand, the algorithm type "dpmsolver" and "sde-dpmsolver" (proposed in this paper before the same author came up with dpmsolver+++ https://huggingface.co/papers/2206.00927) are completely obsolete at this point.

@yiyixuxu
Copy link
Collaborator Author

testing "dpmsolver ++"

testing the implementation against k-diffusion

  • I followed the same math used in k-diffusion so results should match exact
  • diff< 3e-4 for both tests below

use_karras_sigmas=False

import torch
from diffusers import StableDiffusionKDiffusionPipeline, DPMSolverMultistepScheduler, StableDiffusionPipeline
import gc
import numpy as np

# test1: use_karras_sigmas=False
seed = 33

pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4")
pipe = pipe.to("cuda")
pipe.scheduler = DPMSolverMultistepScheduler.from_config(
    pipe.scheduler.config, use_karras_sigmas=False
)

prompt = "an astronaut riding a horse on mars"

generator = torch.Generator(device="cuda").manual_seed(seed)
image_d = pipe(prompt, generator=generator, num_inference_steps=20, output_type='np').images[0]

seed = 33

pipe = StableDiffusionKDiffusionPipeline.from_pretrained(
    "CompVis/stable-diffusion-v1-4"
).to("cuda")
pipe.set_scheduler("sample_dpmpp_2m")

prompt = "an astronaut riding a horse on mars"

generator = torch.Generator(device="cuda").manual_seed(seed)
image_k = pipe(
    prompt, generator=generator, num_inference_steps=20, use_karras_sigmas=False, output_type='np'
).images[0]

print(f"compare: {np.max(np.abs((image_d - image_k)))}")

-> 0.0002550482749938965

use_karras_sigmas=True

seed = 33

pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4")
pipe = pipe.to("cuda")
pipe.scheduler = DPMSolverMultistepScheduler.from_config(
    pipe.scheduler.config, use_karras_sigmas=True
)

prompt = "an astronaut riding a horse on mars"

generator = torch.Generator(device="cuda").manual_seed(seed)
image_d = pipe(prompt, generator=generator, num_inference_steps=20, output_type='np').images[0]

seed = 33

pipe = StableDiffusionKDiffusionPipeline.from_pretrained(
    "CompVis/stable-diffusion-v1-4"
).to("cuda")
pipe.set_scheduler("sample_dpmpp_2m")

prompt = "an astronaut riding a horse on mars"

generator = torch.Generator(device="cuda").manual_seed(seed)
image_k = pipe(
    prompt, generator=generator, num_inference_steps=20, use_karras_sigmas=True, output_type='np'
).images[0]

print(f"compare: {np.max(np.abs((image_d - image_k)))}")

-> 0.000287860631942749

compare against current implementation (main branch)

  • there are some numerical difference if we compare numpy output, but visually they are pretty identical I think

use_karras_sigmas=False

import torch
from diffusers import StableDiffusionKDiffusionPipeline, DPMSolverMultistepScheduler, StableDiffusionPipeline
import gc

seed = 33

pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4")
pipe = pipe.to("cuda")
pipe.scheduler = DPMSolverMultistepScheduler.from_config(
    pipe.scheduler.config, use_karras_sigmas=False
)

prompt = "an astronaut riding a horse on mars"

generator = torch.Generator(device="cuda").manual_seed(seed)
image = pipe(prompt, generator=generator, num_inference_steps=20).images[0]

image.save(f"dpmsolver++.png")

current implementation
main_dpmsolver++

This PR
dpmsolver++

use_karras_sigmas=True

seed = 33

pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4")
pipe = pipe.to("cuda")
pipe.scheduler = DPMSolverMultistepScheduler.from_config(
    pipe.scheduler.config, use_karras_sigmas=True
)

prompt = "an astronaut riding a horse on mars"

generator = torch.Generator(device="cuda").manual_seed(seed)
image = pipe(prompt, generator=generator, num_inference_steps=20).images[0]

image.save(f"dpmsolver++_k_sigma.png") 

current implementation
main_dpmsolver++_k_sigma

this PR
dpmsolver++_k_sigma

@yiyixuxu
Copy link
Collaborator Author

think I'm overcomplicating things with this pr - will try a different approach!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants