mirror of
https://github.com/leejet/stable-diffusion.cpp.git
synced 2026-09-24 20:20:37 +00:00
feat: optimize cfg special cases with guidance schdeule (#2033)
This commit is contained in:
parent
88411ef1e0
commit
caa111adf3
@ -2441,6 +2441,7 @@ sd::Tensor<float> StableDiffusionGGML::sample(const std::shared_ptr<DiffusionMod
|
||||
timesteps_tensor,
|
||||
cond,
|
||||
&controls);
|
||||
bool uncond_controls_ready = false;
|
||||
|
||||
static const std::vector<sd::Tensor<float>> empty_ref_latents;
|
||||
bool uncond_without_ref_latents = !img_uncond.empty() &&
|
||||
@ -2530,6 +2531,17 @@ sd::Tensor<float> StableDiffusionGGML::sample(const std::shared_ptr<DiffusionMod
|
||||
return std::move(cached_output);
|
||||
}
|
||||
|
||||
// A re-enabled condition can miss the cache even when the positive pass was reused.
|
||||
if (!uncond_controls_ready && !uncond.empty() &&
|
||||
(&condition == &uncond || &condition == &img_uncond)) {
|
||||
compute_sample_controls(control_image,
|
||||
noised_input,
|
||||
timesteps_tensor,
|
||||
uncond,
|
||||
&controls);
|
||||
uncond_controls_ready = true;
|
||||
}
|
||||
|
||||
for (const auto& extension : generation_extensions) {
|
||||
extension->before_diffusion(diffusion_params, step);
|
||||
}
|
||||
@ -2569,19 +2581,39 @@ sd::Tensor<float> StableDiffusionGGML::sample(const std::shared_ptr<DiffusionMod
|
||||
}
|
||||
}
|
||||
|
||||
float effective_guidance_scale = guidance_schedule.empty()
|
||||
? cfg_scale
|
||||
: guidance_schedule[guidance_schedule.size() - 1 - step];
|
||||
|
||||
float image_guidance_scale = img_cfg_scale;
|
||||
|
||||
constexpr float kEpsilon = 1e-5f;
|
||||
|
||||
bool skip_uncond = false;
|
||||
if (!uncond.empty() && !needs_uncond_denoised && !use_apg_guidance) {
|
||||
if (!img_uncond.empty()) {
|
||||
skip_uncond = std::abs(image_guidance_scale - effective_guidance_scale) < kEpsilon;
|
||||
} else {
|
||||
skip_uncond = std::abs(effective_guidance_scale - 1.0f) < kEpsilon;
|
||||
}
|
||||
}
|
||||
|
||||
bool skip_img_uncond = false;
|
||||
if (!img_uncond.empty() && !needs_uncond_denoised && !use_apg_guidance) {
|
||||
if (!uncond.empty()) {
|
||||
skip_img_uncond = std::abs(image_guidance_scale - 1.0f) < kEpsilon;
|
||||
} else {
|
||||
skip_img_uncond = std::abs(effective_guidance_scale - 1.0f) < kEpsilon;
|
||||
}
|
||||
}
|
||||
|
||||
cond_out = run_condition(*positive_condition, c_concat_override);
|
||||
if (cond_out.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!uncond.empty()) {
|
||||
if (!step_cache.is_step_skipped()) {
|
||||
compute_sample_controls(control_image,
|
||||
noised_input,
|
||||
timesteps_tensor,
|
||||
uncond,
|
||||
&controls);
|
||||
}
|
||||
if (!skip_uncond) {
|
||||
const std::vector<int>* uncond_skip_layers = nullptr;
|
||||
if (is_skiplayer_step && slg_uncond) {
|
||||
LOG_VERBOSE("Skipping layers at uncond step %d\n", step);
|
||||
@ -2595,8 +2627,13 @@ sd::Tensor<float> StableDiffusionGGML::sample(const std::shared_ptr<DiffusionMod
|
||||
if (uncond_out.empty()) {
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
step_cache.invalidate_condition(&uncond);
|
||||
}
|
||||
}
|
||||
|
||||
if (!img_uncond.empty()) {
|
||||
if (!skip_img_uncond) {
|
||||
img_uncond_out = run_condition(img_uncond,
|
||||
img_uncond.c_concat.empty() ? nullptr : &img_uncond.c_concat,
|
||||
nullptr,
|
||||
@ -2605,6 +2642,9 @@ sd::Tensor<float> StableDiffusionGGML::sample(const std::shared_ptr<DiffusionMod
|
||||
if (img_uncond_out.empty()) {
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
step_cache.invalidate_condition(&img_uncond);
|
||||
}
|
||||
}
|
||||
sd::guidance::GuidanceInput guidance_input;
|
||||
guidance_input.step = step;
|
||||
@ -2613,7 +2653,7 @@ sd::Tensor<float> StableDiffusionGGML::sample(const std::shared_ptr<DiffusionMod
|
||||
guidance_input.pred_uncond = uncond_out.empty() ? nullptr : &uncond_out;
|
||||
guidance_input.pred_img_uncond = img_uncond_out.empty() ? nullptr : &img_uncond_out;
|
||||
|
||||
sd::guidance::GuiderOutput guided = guidance_schedule.empty() ? primary_guidance.forward(guidance_input, {}) : primary_guidance.forward(guidance_input, {}, guidance_schedule[guidance_schedule.size() - 1 - step]);
|
||||
sd::guidance::GuiderOutput guided = primary_guidance.forward(guidance_input, {}, effective_guidance_scale);
|
||||
if (guided.pred.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -275,6 +275,26 @@ namespace sd_sample {
|
||||
}
|
||||
}
|
||||
|
||||
void SampleStepCacheDispatcher::invalidate_condition(const void* condition) {
|
||||
if (condition == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (runtime.mode) {
|
||||
case SampleCacheMode::EASYCACHE:
|
||||
runtime.easycache.cache_diffs.erase(condition);
|
||||
break;
|
||||
case SampleCacheMode::UCACHE:
|
||||
runtime.ucache.cache_diffs.erase(condition);
|
||||
break;
|
||||
case SampleCacheMode::CACHEDIT:
|
||||
runtime.cachedit.cache_diffs.erase(condition);
|
||||
break;
|
||||
case SampleCacheMode::NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool SampleStepCacheDispatcher::is_step_skipped() const {
|
||||
switch (runtime.mode) {
|
||||
case SampleCacheMode::EASYCACHE:
|
||||
|
||||
@ -46,6 +46,7 @@ namespace sd_sample {
|
||||
|
||||
bool before_condition(const void* condition, const sd::Tensor<float>& input, sd::Tensor<float>* output);
|
||||
void after_condition(const void* condition, const sd::Tensor<float>& input, const sd::Tensor<float>& output);
|
||||
void invalidate_condition(const void* condition);
|
||||
bool is_step_skipped() const;
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user