Skip to content

Commit 3371b90

Browse files
Add LazyCache variant to EasyCache implementation
Added `LazyCache` support to `EasyCache` implementation for `stable-diffusion.cpp`. - Modified `EasyCacheState` in `easycache.hpp` to support index-based caching (`LazyCache` mode) alongside condition-pointer-based caching (`EasyCache` mode). - Added `is_lazy` flag to `EasyCacheConfig` and `sd_easycache_params_t`. - Updated `stable-diffusion.cpp` to initialize and use the `is_lazy` parameter. - Verified compilation. This allows users to enable `LazyCache` which is more compatible with workflows where condition objects might be unstable, by relying on sequential execution order within a sampling step.
1 parent 6ccc671 commit 3371b90

File tree

3 files changed

+81
-24
lines changed

3 files changed

+81
-24
lines changed

easycache.hpp

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
struct EasyCacheConfig {
1010
bool enabled = false;
11+
bool is_lazy = false;
1112
float reuse_threshold = 0.2f;
1213
float start_percent = 0.15f;
1314
float end_percent = 0.95f;
@@ -28,6 +29,9 @@ struct EasyCacheState {
2829
bool step_active = false;
2930
const SDCondition* anchor_condition = nullptr;
3031
std::unordered_map<const SDCondition*, EasyCacheCacheEntry> cache_diffs;
32+
std::vector<EasyCacheCacheEntry> lazy_cache_diffs;
33+
int current_sub_step_index = 0;
34+
3135
std::vector<float> prev_input;
3236
std::vector<float> prev_output;
3337
float output_prev_norm = 0.0f;
@@ -48,6 +52,8 @@ struct EasyCacheState {
4852
step_active = false;
4953
anchor_condition = nullptr;
5054
cache_diffs.clear();
55+
lazy_cache_diffs.clear();
56+
current_sub_step_index = 0;
5157
prev_input.clear();
5258
prev_output.clear();
5359
output_prev_norm = 0.0f;
@@ -99,10 +105,11 @@ struct EasyCacheState {
99105
if (step_index == current_step_index) {
100106
return;
101107
}
102-
current_step_index = step_index;
103-
skip_current_step = false;
104-
has_last_input_change = false;
105-
step_active = false;
108+
current_step_index = step_index;
109+
current_sub_step_index = 0;
110+
skip_current_step = false;
111+
has_last_input_change = false;
112+
step_active = false;
106113
if (sigma > start_sigma) {
107114
return;
108115
}
@@ -121,31 +128,54 @@ struct EasyCacheState {
121128
}
122129

123130
bool has_cache(const SDCondition* cond) const {
131+
if (config.is_lazy) {
132+
return current_sub_step_index < (int)lazy_cache_diffs.size() && !lazy_cache_diffs[current_sub_step_index].diff.empty();
133+
}
124134
auto it = cache_diffs.find(cond);
125135
return it != cache_diffs.end() && !it->second.diff.empty();
126136
}
127137

128138
void update_cache(const SDCondition* cond, ggml_tensor* input, ggml_tensor* output) {
129-
EasyCacheCacheEntry& entry = cache_diffs[cond];
130-
size_t ne = static_cast<size_t>(ggml_nelements(output));
131-
entry.diff.resize(ne);
139+
EasyCacheCacheEntry* entry = nullptr;
140+
if (config.is_lazy) {
141+
if (current_sub_step_index >= (int)lazy_cache_diffs.size()) {
142+
lazy_cache_diffs.resize(current_sub_step_index + 1);
143+
}
144+
entry = &lazy_cache_diffs[current_sub_step_index];
145+
} else {
146+
entry = &cache_diffs[cond];
147+
}
148+
149+
size_t ne = static_cast<size_t>(ggml_nelements(output));
150+
entry->diff.resize(ne);
132151
float* out_data = (float*)output->data;
133152
float* in_data = (float*)input->data;
134153
for (size_t i = 0; i < ne; ++i) {
135-
entry.diff[i] = out_data[i] - in_data[i];
154+
entry->diff[i] = out_data[i] - in_data[i];
136155
}
137156
}
138157

139158
void apply_cache(const SDCondition* cond, ggml_tensor* input, ggml_tensor* output) {
140-
auto it = cache_diffs.find(cond);
141-
if (it == cache_diffs.end() || it->second.diff.empty()) {
159+
const std::vector<float>* diff = nullptr;
160+
if (config.is_lazy) {
161+
if (current_sub_step_index < (int)lazy_cache_diffs.size()) {
162+
diff = &lazy_cache_diffs[current_sub_step_index].diff;
163+
}
164+
} else {
165+
auto it = cache_diffs.find(cond);
166+
if (it != cache_diffs.end()) {
167+
diff = &it->second.diff;
168+
}
169+
}
170+
171+
if (diff == nullptr || diff->empty()) {
142172
return;
143173
}
174+
144175
copy_ggml_tensor(output, input);
145-
float* out_data = (float*)output->data;
146-
const std::vector<float>& diff = it->second.diff;
147-
for (size_t i = 0; i < diff.size(); ++i) {
148-
out_data[i] += diff[i];
176+
float* out_data = (float*)output->data;
177+
for (size_t i = 0; i < diff->size(); ++i) {
178+
out_data[i] += (*diff)[i];
149179
}
150180
}
151181

@@ -163,14 +193,24 @@ struct EasyCacheState {
163193
if (!step_active) {
164194
return false;
165195
}
166-
if (initial_step) {
167-
anchor_condition = cond;
168-
initial_step = false;
196+
197+
bool is_anchor = false;
198+
if (config.is_lazy) {
199+
is_anchor = (current_sub_step_index == 0);
200+
} else {
201+
if (initial_step) {
202+
anchor_condition = cond;
203+
initial_step = false;
204+
}
205+
is_anchor = (cond == anchor_condition);
169206
}
170-
bool is_anchor = (cond == anchor_condition);
207+
171208
if (skip_current_step) {
172209
if (has_cache(cond)) {
173210
apply_cache(cond, input, output);
211+
if (config.is_lazy) {
212+
current_sub_step_index++;
213+
}
174214
return true;
175215
}
176216
return false;
@@ -202,6 +242,9 @@ struct EasyCacheState {
202242
skip_current_step = true;
203243
total_steps_skipped++;
204244
apply_cache(cond, input, output);
245+
if (config.is_lazy) {
246+
current_sub_step_index++;
247+
}
205248
return true;
206249
} else {
207250
cumulative_change_rate = 0.0f;
@@ -216,7 +259,16 @@ struct EasyCacheState {
216259
return;
217260
}
218261
update_cache(cond, input, output);
219-
if (cond != anchor_condition) {
262+
263+
bool is_anchor = false;
264+
if (config.is_lazy) {
265+
is_anchor = (current_sub_step_index == 0);
266+
current_sub_step_index++;
267+
} else {
268+
is_anchor = (cond == anchor_condition);
269+
}
270+
271+
if (!is_anchor) {
220272
return;
221273
}
222274

@@ -262,4 +314,4 @@ struct EasyCacheState {
262314
cumulative_change_rate = 0.0f;
263315
has_last_input_change = false;
264316
}
265-
};
317+
};

stable-diffusion.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,6 +1547,7 @@ class StableDiffusionGGML {
15471547
} else {
15481548
EasyCacheConfig easycache_config;
15491549
easycache_config.enabled = true;
1550+
easycache_config.is_lazy = easycache_params->is_lazy;
15501551
easycache_config.reuse_threshold = std::max(0.0f, easycache_params->reuse_threshold);
15511552
easycache_config.start_percent = easycache_params->start_percent;
15521553
easycache_config.end_percent = easycache_params->end_percent;
@@ -1563,10 +1564,11 @@ class StableDiffusionGGML {
15631564
easycache_state.init(easycache_config, denoiser.get());
15641565
if (easycache_state.enabled()) {
15651566
easycache_enabled = true;
1566-
LOG_INFO("EasyCache enabled - threshold: %.3f, start_percent: %.2f, end_percent: %.2f",
1567+
LOG_INFO("EasyCache enabled - threshold: %.3f, start_percent: %.2f, end_percent: %.2f, is_lazy: %s",
15671568
easycache_config.reuse_threshold,
15681569
easycache_config.start_percent,
1569-
easycache_config.end_percent);
1570+
easycache_config.end_percent,
1571+
easycache_config.is_lazy ? "true" : "false");
15701572
} else {
15711573
LOG_WARN("EasyCache requested but could not be initialized for this run");
15721574
}
@@ -2440,6 +2442,7 @@ enum lora_apply_mode_t str_to_lora_apply_mode(const char* str) {
24402442
void sd_easycache_params_init(sd_easycache_params_t* easycache_params) {
24412443
*easycache_params = {};
24422444
easycache_params->enabled = false;
2445+
easycache_params->is_lazy = false;
24432446
easycache_params->reuse_threshold = 0.2f;
24442447
easycache_params->start_percent = 0.15f;
24452448
easycache_params->end_percent = 0.95f;
@@ -2651,11 +2654,12 @@ char* sd_img_gen_params_to_str(const sd_img_gen_params_t* sd_img_gen_params) {
26512654
SAFE_STR(sd_img_gen_params->pm_params.id_embed_path),
26522655
BOOL_STR(sd_img_gen_params->vae_tiling_params.enabled));
26532656
snprintf(buf + strlen(buf), 4096 - strlen(buf),
2654-
"easycache: %s (threshold=%.3f, start=%.2f, end=%.2f)\n",
2657+
"easycache: %s (threshold=%.3f, start=%.2f, end=%.2f, is_lazy=%s)\n",
26552658
sd_img_gen_params->easycache.enabled ? "enabled" : "disabled",
26562659
sd_img_gen_params->easycache.reuse_threshold,
26572660
sd_img_gen_params->easycache.start_percent,
2658-
sd_img_gen_params->easycache.end_percent);
2661+
sd_img_gen_params->easycache.end_percent,
2662+
sd_img_gen_params->easycache.is_lazy ? "true" : "false");
26592663
free(sample_params_str);
26602664
return buf;
26612665
}

stable-diffusion.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ typedef struct {
232232

233233
typedef struct {
234234
bool enabled;
235+
bool is_lazy;
235236
float reuse_threshold;
236237
float start_percent;
237238
float end_percent;

0 commit comments

Comments
 (0)