Skip to content

Commit 37690b7

Browse files
committed
Add gradient estimation sampler
1 parent 7fa7ed8 commit 37690b7

File tree

5 files changed

+49
-4
lines changed

5 files changed

+49
-4
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ arguments:
328328
--skip-layer-start START SLG enabling point: (default: 0.01)
329329
--skip-layer-end END SLG disabling point: (default: 0.2)
330330
--scheduler {discrete, karras, exponential, ays, gits, smoothstep, sgm_uniform, simple} Denoiser sigma scheduler (default: discrete)
331-
--sampling-method {euler, euler_a, heun, dpm2, dpm++2s_a, dpm++2m, dpm++2mv2, ipndm, ipndm_v, lcm, ddim_trailing, tcd}
331+
--sampling-method {euler, euler_a, heun, dpm2, dpm++2s_a, dpm++2m, dpm++2mv2, ipndm, ipndm_v, lcm, ddim_trailing, tcd, gradient_estimation}
332332
sampling method (default: "euler" for Flux/SD3/Wan, "euler_a" otherwise)
333333
--timestep-shift N shift timestep for NitroFusion models, default: 0, recommended N for NitroSD-Realism around 250 and 500 for NitroSD-Vibrant
334334
--steps STEPS number of sample steps (default: 20)
@@ -342,7 +342,7 @@ arguments:
342342
--high-noise-skip-layer-start (high noise) SLG enabling point: (default: 0.01)
343343
--high-noise-skip-layer-end END (high noise) SLG disabling point: (default: 0.2)
344344
--high-noise-scheduler {discrete, karras, exponential, ays, gits, smoothstep, sgm_uniform, simple} Denoiser sigma scheduler (default: discrete)
345-
--high-noise-sampling-method {euler, euler_a, heun, dpm2, dpm++2s_a, dpm++2m, dpm++2mv2, ipndm, ipndm_v, lcm, ddim_trailing, tcd}
345+
--high-noise-sampling-method {euler, euler_a, heun, dpm2, dpm++2s_a, dpm++2m, dpm++2mv2, ipndm, ipndm_v, lcm, ddim_trailing, tcd, gradient_estimation}
346346
(high noise) sampling method (default: "euler_a")
347347
--high-noise-steps STEPS (high noise) number of sample steps (default: -1 = auto)
348348
SLG will be enabled at step int([STEPS]*[START]) and disabled at int([STEPS]*[END])

denoiser.hpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,7 +1462,50 @@ static void sample_k_diffusion(sample_method_t method,
14621462
}
14631463
}
14641464
} break;
1465+
case GRADIENT_ESTIMATION: {
1466+
// See: https://github.com/crowsonkb/k-diffusion/pull/114
1467+
struct ggml_tensor* noise = ggml_dup_tensor(work_ctx, x);
1468+
struct ggml_tensor* d = ggml_dup_tensor(work_ctx, x);
1469+
struct ggml_tensor* x_2 = ggml_dup_tensor(work_ctx, x);
1470+
1471+
for (int i = 0; i < steps; i++) {
1472+
float sigma = sigmas[i];
1473+
1474+
ggml_tensor* denoised = model(x, sigma, i + 1);
14651475

1476+
float* vec_d = (float*)d->data;
1477+
float* vec_x = (float*)x->data;
1478+
float* vec_x_2 = (float*)x_2->data;
1479+
float* vec_denoised = (float*)denoised->data;
1480+
1481+
for (int j = 0; j < ggml_nelements(d); j++) {
1482+
vec_d[j] = (vec_x[j] - vec_denoised[j]) / sigma;
1483+
}
1484+
1485+
float sigma_2 = sigmas[i] * 0.5;
1486+
1487+
ggml_tensor_set_f32_randn(noise, rng);
1488+
1489+
for (int j = 0; j < ggml_nelements(x); j++) {
1490+
vec_x_2[j] = vec_x[j] + sigma_2 * ((float*)noise->data)[j];
1491+
}
1492+
1493+
ggml_tensor* denoised_2 = model(x_2, sigma, i + 1);
1494+
float* vec_denoised_2 = (float*)denoised_2->data;
1495+
1496+
// d = (x - denoised) / sigma
1497+
for (int j = 0; j < ggml_nelements(d); j++) {
1498+
float vec_d_2 = (vec_x_2[j] - vec_denoised_2[j]) / sigma;
1499+
vec_d[j] += (vec_d_2 - vec_d[j]) * 1.f / (sigma_2 * sigma_2) * ((float*)noise->data)[j];
1500+
}
1501+
1502+
float dt = sigmas[i + 1] - sigma;
1503+
// x = x + d * dt
1504+
for (int j = 0; j < ggml_nelements(x); j++) {
1505+
vec_x[j] = vec_x[j] + vec_d[j] * dt;
1506+
}
1507+
}
1508+
} break;
14661509
default:
14671510
LOG_ERROR("Attempting to sample with nonexisting sample method %i", method);
14681511
abort();

examples/cli/main.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ void print_usage(int argc, const char* argv[]) {
247247
printf(" --skip-layer-start START SLG enabling point: (default: 0.01)\n");
248248
printf(" --skip-layer-end END SLG disabling point: (default: 0.2)\n");
249249
printf(" --scheduler {discrete, karras, exponential, ays, gits, smoothstep, sgm_uniform, simple} Denoiser sigma scheduler (default: discrete)\n");
250-
printf(" --sampling-method {euler, euler_a, heun, dpm2, dpm++2s_a, dpm++2m, dpm++2mv2, ipndm, ipndm_v, lcm, ddim_trailing, tcd}\n");
250+
printf(" --sampling-method {euler, euler_a, heun, dpm2, dpm++2s_a, dpm++2m, dpm++2mv2, ipndm, ipndm_v, lcm, ddim_trailing, tcd, gradient_estimation}\n");
251251
printf(" sampling method (default: \"euler\" for Flux/SD3/Wan, \"euler_a\" otherwise)\n");
252252
printf(" --timestep-shift N shift timestep for NitroFusion models, default: 0, recommended N for NitroSD-Realism around 250 and 500 for NitroSD-Vibrant\n");
253253
printf(" --steps STEPS number of sample steps (default: 20)\n");
@@ -261,7 +261,7 @@ void print_usage(int argc, const char* argv[]) {
261261
printf(" --high-noise-skip-layer-start (high noise) SLG enabling point: (default: 0.01)\n");
262262
printf(" --high-noise-skip-layer-end END (high noise) SLG disabling point: (default: 0.2)\n");
263263
printf(" --high-noise-scheduler {discrete, karras, exponential, ays, gits, smoothstep, sgm_uniform, simple} Denoiser sigma scheduler (default: discrete)\n");
264-
printf(" --high-noise-sampling-method {euler, euler_a, heun, dpm2, dpm++2s_a, dpm++2m, dpm++2mv2, ipndm, ipndm_v, lcm, ddim_trailing, tcd}\n");
264+
printf(" --high-noise-sampling-method {euler, euler_a, heun, dpm2, dpm++2s_a, dpm++2m, dpm++2mv2, ipndm, ipndm_v, lcm, ddim_trailing, tcd, gradient_estimation}\n");
265265
printf(" (high noise) sampling method (default: \"euler_a\")\n");
266266
printf(" --high-noise-steps STEPS (high noise) number of sample steps (default: -1 = auto)\n");
267267
printf(" SLG will be enabled at step int([STEPS]*[START]) and disabled at int([STEPS]*[END])\n");

stable-diffusion.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,7 @@ const char* sample_method_to_str[] = {
16121612
"ddim_trailing",
16131613
"tcd",
16141614
"euler_a",
1615+
"gradient_estimation",
16151616
};
16161617

16171618
const char* sd_sample_method_name(enum sample_method_t sample_method) {

stable-diffusion.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ enum sample_method_t {
4848
DDIM_TRAILING,
4949
TCD,
5050
EULER_A,
51+
GRADIENT_ESTIMATION,
5152
SAMPLE_METHOD_COUNT
5253
};
5354

0 commit comments

Comments
 (0)