fix diffusers samplers

This commit is contained in:
Vladimir Mandic
2023-07-15 22:40:00 -04:00
parent f773c782fa
commit e2b33b81d3
7 changed files with 43 additions and 37 deletions
+2 -2
View File
@@ -285,6 +285,8 @@ def check_python():
def check_torch():
if args.quick:
return
if args.skip_torch:
log.info('Skipping Torch tests')
if args.profile:
pr = cProfile.Profile()
pr.enable()
@@ -330,8 +332,6 @@ def check_torch():
torch_command = os.environ.get('TORCH_COMMAND', 'torch torchvision')
if 'torch' in torch_command and not args.version:
install(torch_command, 'torch torchvision')
if args.skip_torch:
log.info('Skipping Torch tests')
else:
try:
import torch
+1 -1
View File
@@ -67,7 +67,7 @@ def torch_gc(force=False):
if oom > previous_oom:
previous_oom = oom
shared.log.warning(f'GPU out-of-memory error: {mem}')
if used > 90:
if used > 95:
shared.log.warning(f'GPU high memory utilization: {used}% {mem}')
force = True
-2
View File
@@ -123,8 +123,6 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s
width = int(image.width * scale_by)
height = int(image.height * scale_by)
assert 0. <= denoising_strength <= 1., 'can only work with strength in [0.0, 1.0]'
p = processing.StableDiffusionProcessingImg2Img(
sd_model=shared.sd_model,
outpath_samples=shared.opts.outdir_samples or shared.opts.outdir_img2img_samples,
+12 -13
View File
@@ -278,7 +278,7 @@ class Processed:
self.sd_model_hash = shared.sd_model.sd_model_hash
self.seed_resize_from_w = p.seed_resize_from_w
self.seed_resize_from_h = p.seed_resize_from_h
self.denoising_strength = getattr(p, 'denoising_strength', None)
self.denoising_strength = p.denoising_strength
self.extra_generation_params = p.extra_generation_params
self.index_of_first_image = index_of_first_image
self.styles = p.styles
@@ -466,7 +466,7 @@ def create_infotext(p: StableDiffusionProcessing, all_prompts, all_seeds, all_su
"Variation seed": None if p.subseed_strength == 0 else all_subseeds[index],
"Variation seed strength": None if p.subseed_strength == 0 else p.subseed_strength,
"Seed resize from": None if p.seed_resize_from_w == 0 or p.seed_resize_from_h == 0 else f"{p.seed_resize_from_w}x{p.seed_resize_from_h}",
"Denoising strength": getattr(p, 'denoising_strength', None),
"Denoising strength": p.denoising_strength,
"Conditional mask weight": getattr(p, "inpainting_mask_weight", shared.opts.inpainting_mask_weight) if p.is_using_inpainting_conditioning else None,
"Clip skip": p.clip_skip if p.clip_skip > 1 else None,
"ENSD": opts.eta_noise_seed_delta if uses_ensd else None,
@@ -728,11 +728,11 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
del samples_ddim
elif shared.backend == Backend.DIFFUSERS:
if (not hasattr(shared.sd_model.scheduler, 'name')) or (shared.sd_model.scheduler.name != p.sampler_name):
sampler = sd_samplers.all_samplers_map.get(p.sampler_name, None)
if sampler is None:
sampler = sd_samplers.all_samplers_map.get("UniPC")
shared.sd_model.scheduler = sd_samplers.create_sampler(sampler.name, shared.sd_model) # TODO(Patrick): For wrapped pipelines this is currently a no-op
# if (not hasattr(shared.sd_model.scheduler, 'name')) or (shared.sd_model.scheduler.name != p.sampler_name):
sampler = sd_samplers.all_samplers_map.get(p.sampler_name, None)
if sampler is None:
sampler = sd_samplers.all_samplers_map.get("UniPC")
sd_samplers.create_sampler(sampler.name, shared.sd_model) # TODO(Patrick): For wrapped pipelines this is currently a no-op
cross_attention_kwargs={}
if lora_state['active']:
@@ -746,7 +746,6 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
# TODO(PVP): change out to latents once possible with `diffusers`
task_specific_kwargs = {"image": p.init_images[0], "mask_image": p.image_mask, "strength": p.denoising_strength}
shared.sd_model.to(devices.device)
pipe_args = set_pipeline_args(
model=shared.sd_model,
@@ -766,11 +765,11 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
shared.log.debug('Moving base model to CPU')
shared.sd_model.to('cpu')
if (not hasattr(shared.sd_refiner.scheduler, 'name')) or (shared.sd_refiner.scheduler.name != p.latent_sampler):
sampler = sd_samplers.all_samplers_map.get(p.latent_sampler, None)
if sampler is None:
sampler = sd_samplers.all_samplers_map.get("UniPC")
shared.sd_refiner.scheduler = sd_samplers.create_sampler(sampler.name, shared.sd_refiner) # TODO(Patrick): For wrapped pipelines this is currently a no-op
# if (not hasattr(shared.sd_refiner.scheduler, 'name')) or (shared.sd_refiner.scheduler.name != p.latent_sampler):
sampler = sd_samplers.all_samplers_map.get(p.latent_sampler, None)
if sampler is None:
sampler = sd_samplers.all_samplers_map.get("UniPC")
sd_samplers.create_sampler(sampler.name, shared.sd_refiner) # TODO(Patrick): For wrapped pipelines this is currently a no-op
shared.sd_refiner.to(devices.device)
devices.torch_gc()
+2
View File
@@ -47,6 +47,8 @@ def create_sampler(name, model):
return sampler
elif shared.backend == shared.Backend.DIFFUSERS:
sampler = config.constructor(model)
if not hasattr(model, 'scheduler_config'):
model.scheduler_config = sampler.sampler.config.copy()
model.scheduler = sampler.sampler
return sampler.sampler
else:
+25 -18
View File
@@ -22,20 +22,22 @@ except Exception as e:
log.error(f'Diffusers import error: version={diffusers.__version__} error: {e}')
config = {
'All': { 'num_train_timesteps': 1000, 'beta_schedule': 'linear', 'prediction_type': 'epsilon' },
'UniPC': { 'beta_start': 0.0001, 'beta_end': 0.02,'solver_order': 2, 'thresholding': False, 'sample_max_value': 1.0, 'predict_x0': 'bh2', 'lower_order_final': True },
'DDIM': { 'beta_start': 0.0001, 'beta_end': 0.02,'clip_sample': True, 'set_alpha_to_one': True, 'steps_offset': 0, 'thresholding': False, 'clip_sample_range': 1.0, 'sample_max_value': 1.0, 'timestep_spacing': 'linspace', 'rescale_betas_zero_snr': False },
'DDPM': { 'beta_start': 0.0001, 'beta_end': 0.02,'variance_type': "fixed_small", 'clip_sample': True, 'thresholding': False, 'clip_sample_range': 1.0, 'sample_max_value': 1.0, 'timestep_spacing': 'linspace'},
'KDPM2': {'beta_start': 0.00085, 'beta_end': 0.012, 'steps_offset': 0 },
'KDPM2 a': {'beta_start': 0.00085, 'beta_end': 0.012, 'steps_offset': 0 },
'DEIS': { 'beta_start': 0.0001, 'beta_end': 0.02,'solver_order': 2, 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "deis", 'solver_type': "logrho", 'lower_order_final': True },
'Euler': {'beta_start': 0.0001, 'beta_end': 0.02, 'interpolation_type': "linear", 'use_karras_sigmas': False },
'Euler a': { 'beta_start': 0.0001, 'beta_end': 0.02 },
'Heun': { 'beta_start': 0.0001, 'beta_end': 0.02,'use_karras_sigmas': False },
'PNDM': { 'beta_start': 0.0001, 'beta_end': 0.02,'skip_prk_steps': False, 'set_alpha_to_one': False, 'steps_offset': 0 },
'DPM 1S': { 'beta_start': 0.0001, 'beta_end': 0.02,'solver_order': 2, 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "dpmsolver++", 'solver_type': "midpoint", 'lower_order_final': True, 'use_karras_sigmas': False },
'DPM 2M': { 'beta_start': 0.0001, 'beta_end': 0.02,'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "dpmsolver++", 'solver_type': "midpoint", 'lower_order_final': True, 'use_karras_sigmas': False },
'LMSD': { 'beta_start': 0.0001, 'beta_end': 0.02,'use_karras_sigmas': False, 'timestep_spacing': 'linspace', 'steps_offset': 0 },
# TODO beta_start, beta_end are typically per-scheduler, but we don't want them as they should be taken from the model itself as those are values model was trained on
# TODO prediction_type is ideally set in model as well, but it maybe needed that we do auto-detect of model type in the future
'All': { 'num_train_timesteps': 1000, 'beta_start': 0.0001, 'beta_end': 0.02, 'beta_schedule': 'linear', 'prediction_type': 'epsilon' },
'DDIM': { 'clip_sample': True, 'set_alpha_to_one': True, 'steps_offset': 0, 'thresholding': False, 'clip_sample_range': 1.0, 'sample_max_value': 1.0, 'timestep_spacing': 'linspace', 'rescale_betas_zero_snr': False },
'DDPM': { 'variance_type': "fixed_small", 'clip_sample': True, 'thresholding': False, 'clip_sample_range': 1.0, 'sample_max_value': 1.0, 'timestep_spacing': 'linspace'},
'DEIS': { 'solver_order': 2, 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "deis", 'solver_type': "logrho", 'lower_order_final': True },
'DPM 1S': { 'solver_order': 2, 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "dpmsolver++", 'solver_type': "midpoint", 'lower_order_final': True, 'use_karras_sigmas': False },
'DPM 2M': { 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "dpmsolver++", 'solver_type': "midpoint", 'lower_order_final': True, 'use_karras_sigmas': False },
'Euler a': { },
'Euler': { 'interpolation_type': "linear", 'use_karras_sigmas': False },
'Heun': { 'use_karras_sigmas': False },
'KDPM2 a': { 'steps_offset': 0 },
'KDPM2': { 'steps_offset': 0 },
'LMSD': { 'use_karras_sigmas': False, 'timestep_spacing': 'linspace', 'steps_offset': 0 },
'PNDM': { 'skip_prk_steps': False, 'set_alpha_to_one': False, 'steps_offset': 0 },
'UniPC': { 'solver_order': 2, 'thresholding': False, 'sample_max_value': 1.0, 'predict_x0': 'bh2', 'lower_order_final': True },
}
samplers_data_diffusers = [
@@ -57,17 +59,22 @@ samplers_data_diffusers = [
class DiffusionSampler:
def __init__(self, name, constructor, model, **kwargs):
self.config = {}
self.config = config['All'].copy()
self.config = config['All'].copy() # apply global defaults
if not hasattr(model, 'scheduler'):
return
for key, value in config.get(name, {}).items(): # diffusers defaults
for key, value in config.get(name, {}).items(): # apply diffusers per-scheduler defaults
self.config[key] = value
for key, value in model.scheduler.config.items(): # model defaults
if hasattr(model.scheduler, 'scheduler_config'): # find model defaults
orig_config = model.scheduler.scheduler_config
else:
orig_config = model.scheduler.config
for key, value in orig_config.items(): # apply model defaults
if key in self.config:
self.config[key] = value
for key, value in kwargs.items(): # user args
for key, value in kwargs.items(): # apply user args, if any
if key in self.config:
self.config[key] = value
# finally apply user preferences
if opts.schedulers_prediction_type != 'default':
self.config['prediction_type'] = opts.schedulers_prediction_type
if opts.schedulers_beta_schedule != 'default':
+1 -1
Submodule wiki updated: fea0bd7d59...f0aae4958a