mirror of
https://github.com/leejet/stable-diffusion.cpp.git
synced 2026-07-24 03:40:53 -05:00
Compare commits
5 Commits
master-09c
...
master-3bf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bf1665885 | ||
|
|
3001c23f7d | ||
|
|
ed374983f3 | ||
|
|
4c96185fcc | ||
|
|
fbd18e1059 |
2
ggml
2
ggml
Submodule ggml updated: a0811d8181...4efc7b208f
4
rng.h
4
rng.h
@@ -16,7 +16,7 @@ class STDDefaultRNG : public RNG {
|
||||
|
||||
public:
|
||||
void manual_seed(uint64_t seed) {
|
||||
generator.seed(seed);
|
||||
generator.seed((unsigned int)seed);
|
||||
}
|
||||
|
||||
std::vector<float> randn(uint32_t n) {
|
||||
@@ -24,7 +24,7 @@ class STDDefaultRNG : public RNG {
|
||||
float mean = 0.0;
|
||||
float stddev = 1.0;
|
||||
std::normal_distribution<float> distribution(mean, stddev);
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
float random_number = distribution(generator);
|
||||
result.push_back(random_number);
|
||||
}
|
||||
|
||||
18
rng_philox.h
18
rng_philox.h
@@ -16,8 +16,8 @@ class PhiloxRNG : public RNG {
|
||||
private:
|
||||
std::vector<uint32_t> philox_m = {0xD2511F53, 0xCD9E8D57};
|
||||
std::vector<uint32_t> philox_w = {0x9E3779B9, 0xBB67AE85};
|
||||
float two_pow32_inv = 2.3283064e-10;
|
||||
float two_pow32_inv_2pi = 2.3283064e-10 * 6.2831855;
|
||||
float two_pow32_inv = 2.3283064e-10f;
|
||||
float two_pow32_inv_2pi = 2.3283064e-10f * 6.2831855f;
|
||||
|
||||
std::vector<uint32_t> uint32(uint64_t x) {
|
||||
std::vector<uint32_t> result(2);
|
||||
@@ -27,10 +27,10 @@ class PhiloxRNG : public RNG {
|
||||
}
|
||||
|
||||
std::vector<std::vector<uint32_t>> uint32(const std::vector<uint64_t>& x) {
|
||||
int N = x.size();
|
||||
uint32_t N = (uint32_t)x.size();
|
||||
std::vector<std::vector<uint32_t>> result(2, std::vector<uint32_t>(N));
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
for (uint32_t i = 0; i < N; ++i) {
|
||||
result[0][i] = static_cast<uint32_t>(x[i] & 0xFFFFFFFF);
|
||||
result[1][i] = static_cast<uint32_t>(x[i] >> 32);
|
||||
}
|
||||
@@ -41,7 +41,7 @@ class PhiloxRNG : public RNG {
|
||||
// A single round of the Philox 4x32 random number generator.
|
||||
void philox4_round(std::vector<std::vector<uint32_t>>& counter,
|
||||
const std::vector<std::vector<uint32_t>>& key) {
|
||||
uint32_t N = counter[0].size();
|
||||
uint32_t N = (uint32_t)counter[0].size();
|
||||
for (uint32_t i = 0; i < N; i++) {
|
||||
std::vector<uint32_t> v1 = uint32(static_cast<uint64_t>(counter[0][i]) * static_cast<uint64_t>(philox_m[0]));
|
||||
std::vector<uint32_t> v2 = uint32(static_cast<uint64_t>(counter[2][i]) * static_cast<uint64_t>(philox_m[1]));
|
||||
@@ -63,7 +63,7 @@ class PhiloxRNG : public RNG {
|
||||
std::vector<std::vector<uint32_t>> philox4_32(std::vector<std::vector<uint32_t>>& counter,
|
||||
std::vector<std::vector<uint32_t>>& key,
|
||||
int rounds = 10) {
|
||||
uint32_t N = counter[0].size();
|
||||
uint32_t N = (uint32_t)counter[0].size();
|
||||
for (int i = 0; i < rounds - 1; ++i) {
|
||||
philox4_round(counter, key);
|
||||
|
||||
@@ -81,7 +81,7 @@ class PhiloxRNG : public RNG {
|
||||
float u = x * two_pow32_inv + two_pow32_inv / 2;
|
||||
float v = y * two_pow32_inv_2pi + two_pow32_inv_2pi / 2;
|
||||
|
||||
float s = sqrt(-2.0 * log(u));
|
||||
float s = sqrt(-2.0f * log(u));
|
||||
|
||||
float r1 = s * sin(v);
|
||||
return r1;
|
||||
@@ -115,8 +115,8 @@ class PhiloxRNG : public RNG {
|
||||
std::vector<std::vector<uint32_t>> g = philox4_32(counter, key_uint32);
|
||||
|
||||
std::vector<float> result;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
result.push_back(box_muller(g[0][i], g[1][i]));
|
||||
for (uint32_t i = 0; i < n; ++i) {
|
||||
result.push_back(box_muller((float)g[0][i], (float)g[1][i]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "rng_philox.h"
|
||||
#include "stable-diffusion.h"
|
||||
|
||||
#define EPS 1e-05f
|
||||
|
||||
static SDLogLevel log_level = SDLogLevel::INFO;
|
||||
|
||||
#define __FILENAME__ "stable-diffusion.cpp"
|
||||
@@ -120,9 +122,9 @@ ggml_tensor* load_tensor_from_file(ggml_context* ctx, const std::string& file_pa
|
||||
}
|
||||
|
||||
void ggml_tensor_set_f32_randn(struct ggml_tensor* tensor, std::shared_ptr<RNG> rng) {
|
||||
uint32_t n = ggml_nelements(tensor);
|
||||
uint32_t n = (uint32_t)ggml_nelements(tensor);
|
||||
std::vector<float> random_numbers = rng->randn(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
ggml_set_f32_1d(tensor, i, random_numbers[i]);
|
||||
}
|
||||
}
|
||||
@@ -436,12 +438,12 @@ std::vector<std::pair<std::string, float>> parse_prompt_attention(const std::str
|
||||
std::string weight = m[1];
|
||||
|
||||
if (text == "(") {
|
||||
round_brackets.push_back(res.size());
|
||||
round_brackets.push_back((int)res.size());
|
||||
} else if (text == "[") {
|
||||
square_brackets.push_back(res.size());
|
||||
square_brackets.push_back((int)res.size());
|
||||
} else if (!weight.empty()) {
|
||||
if (!round_brackets.empty()) {
|
||||
multiply_range(round_brackets.back(), std::stod(weight));
|
||||
multiply_range(round_brackets.back(), std::stof(weight));
|
||||
round_brackets.pop_back();
|
||||
}
|
||||
} else if (text == ")" && !round_brackets.empty()) {
|
||||
@@ -586,7 +588,7 @@ struct ResidualAttentionBlock {
|
||||
|
||||
// layer norm 1
|
||||
{
|
||||
x = ggml_norm(ctx, x, 1e-6f);
|
||||
x = ggml_norm(ctx, x, EPS);
|
||||
x = ggml_add(ctx,
|
||||
ggml_mul(ctx, ggml_repeat(ctx, ln1_w, x), x),
|
||||
ggml_repeat(ctx, ln1_b, x));
|
||||
@@ -636,7 +638,7 @@ struct ResidualAttentionBlock {
|
||||
|
||||
// layer norm 2
|
||||
{
|
||||
x = ggml_norm(ctx, x, 1e-6f);
|
||||
x = ggml_norm(ctx, x, EPS);
|
||||
|
||||
x = ggml_add(ctx, ggml_mul(ctx, ggml_repeat(ctx, ln2_w, x), x),
|
||||
ggml_repeat(ctx, ln2_b, x));
|
||||
@@ -766,7 +768,7 @@ struct CLIPTextModel {
|
||||
|
||||
// final layer norm
|
||||
{
|
||||
x = ggml_norm(ctx, x, 1e-6f);
|
||||
x = ggml_norm(ctx, x, EPS);
|
||||
|
||||
x = ggml_add(ctx, ggml_mul(ctx, ggml_repeat(ctx, final_ln_w, x), x),
|
||||
ggml_repeat(ctx, final_ln_b, x));
|
||||
@@ -1200,7 +1202,7 @@ struct SpatialTransformer {
|
||||
// layer norm 1
|
||||
{
|
||||
x = ggml_reshape_2d(ctx, x, c, w * h * n);
|
||||
x = ggml_norm(ctx, x, 1e-6f);
|
||||
x = ggml_norm(ctx, x, EPS);
|
||||
x = ggml_add(ctx,
|
||||
ggml_mul(ctx,
|
||||
ggml_repeat(ctx, transformer.norm1_w, x),
|
||||
@@ -1248,7 +1250,7 @@ struct SpatialTransformer {
|
||||
|
||||
// layer norm 2
|
||||
{
|
||||
x = ggml_norm(ctx, x, 1e-6f);
|
||||
x = ggml_norm(ctx, x, EPS);
|
||||
x = ggml_add(ctx,
|
||||
ggml_mul(ctx,
|
||||
ggml_repeat(ctx, transformer.norm2_w, x), x),
|
||||
@@ -1299,7 +1301,7 @@ struct SpatialTransformer {
|
||||
// layer norm 3
|
||||
{
|
||||
x = ggml_reshape_2d(ctx, x, c, h * w * n); // [N * h * w, in_channels]
|
||||
x = ggml_norm(ctx, x, 1e-6f);
|
||||
x = ggml_norm(ctx, x, EPS);
|
||||
x = ggml_add(ctx,
|
||||
ggml_mul(ctx,
|
||||
ggml_repeat(ctx, transformer.norm3_w, x), x),
|
||||
@@ -2705,13 +2707,13 @@ struct DiscreteSchedule : SigmaSchedule {
|
||||
if (n == 0) {
|
||||
return result;
|
||||
} else if (n == 1) {
|
||||
result.push_back(t_to_sigma(t_max));
|
||||
result.push_back(t_to_sigma((float)t_max));
|
||||
result.push_back(0);
|
||||
return result;
|
||||
}
|
||||
|
||||
float step = static_cast<float>(t_max) / static_cast<float>(n - 1);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
for (uint32_t i = 0; i < n; ++i) {
|
||||
float t = t_max - step * i;
|
||||
result.push_back(t_to_sigma(t));
|
||||
}
|
||||
@@ -2724,17 +2726,17 @@ struct KarrasSchedule : SigmaSchedule {
|
||||
std::vector<float> get_sigmas(uint32_t n) {
|
||||
// These *COULD* be function arguments here,
|
||||
// but does anybody ever bother to touch them?
|
||||
float sigma_min = 0.1;
|
||||
float sigma_max = 10.;
|
||||
float rho = 7.;
|
||||
float sigma_min = 0.1f;
|
||||
float sigma_max = 10.f;
|
||||
float rho = 7.f;
|
||||
|
||||
std::vector<float> result(n + 1);
|
||||
|
||||
float min_inv_rho = pow(sigma_min, (1. / rho));
|
||||
float max_inv_rho = pow(sigma_max, (1. / rho));
|
||||
for (int i = 0; i < n; i++) {
|
||||
float min_inv_rho = pow(sigma_min, (1.f / rho));
|
||||
float max_inv_rho = pow(sigma_max, (1.f / rho));
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
// Eq. (5) from Karras et al 2022
|
||||
result[i] = pow(max_inv_rho + (float)i / ((float)n - 1.) * (min_inv_rho - max_inv_rho), rho);
|
||||
result[i] = pow(max_inv_rho + (float)i / ((float)n - 1.f) * (min_inv_rho - max_inv_rho), rho);
|
||||
}
|
||||
result[n] = 0.;
|
||||
return result;
|
||||
@@ -3155,6 +3157,8 @@ class StableDiffusionGGML {
|
||||
struct ggml_tensor* c = ggml_new_tensor_4d(res_ctx, GGML_TYPE_F32, 1024, 2, 1, 1);
|
||||
ggml_set_f32(c, 0.5);
|
||||
|
||||
struct ggml_cplan cplan;
|
||||
|
||||
size_t ctx_size = 10 * 1024 * 1024; // 10MB
|
||||
// calculate the amount of memory required
|
||||
{
|
||||
@@ -3179,7 +3183,7 @@ class StableDiffusionGGML {
|
||||
ctx_size += ggml_used_mem(ctx) + ggml_used_mem_of_data(ctx);
|
||||
|
||||
struct ggml_cgraph* diffusion_graph = ggml_build_forward_ctx(ctx, out);
|
||||
struct ggml_cplan cplan = ggml_graph_plan(diffusion_graph, n_threads);
|
||||
cplan = ggml_graph_plan(diffusion_graph, n_threads);
|
||||
|
||||
ctx_size += cplan.work_size;
|
||||
LOG_DEBUG("diffusion context need %.2fMB static memory, with work_size needing %.2fMB",
|
||||
@@ -3212,7 +3216,7 @@ class StableDiffusionGGML {
|
||||
ggml_hold_dynamic_tensor(out);
|
||||
|
||||
struct ggml_cgraph* diffusion_graph = ggml_build_forward_ctx(ctx, out);
|
||||
struct ggml_cplan cplan = ggml_graph_plan(diffusion_graph, n_threads);
|
||||
cplan = ggml_graph_plan(diffusion_graph, n_threads);
|
||||
|
||||
ggml_set_dynamic(ctx, false);
|
||||
struct ggml_tensor* buf = ggml_new_tensor_1d(ctx, GGML_TYPE_I8, cplan.work_size);
|
||||
@@ -3257,6 +3261,7 @@ class StableDiffusionGGML {
|
||||
true);
|
||||
std::vector<int>& tokens = tokens_and_weights.first;
|
||||
std::vector<float>& weights = tokens_and_weights.second;
|
||||
struct ggml_cplan cplan;
|
||||
size_t ctx_size = 10 * 1024 * 1024; // 10MB
|
||||
// calculate the amount of memory required
|
||||
{
|
||||
@@ -3278,8 +3283,8 @@ class StableDiffusionGGML {
|
||||
|
||||
struct ggml_tensor* hidden_states = cond_stage_model.text_model.forward(ctx, input_ids);
|
||||
|
||||
struct ggml_cgraph cond_graph = ggml_build_forward(hidden_states);
|
||||
struct ggml_cplan cplan = ggml_graph_plan(&cond_graph, n_threads);
|
||||
struct ggml_cgraph* cond_graph = ggml_build_forward_ctx(ctx, hidden_states);
|
||||
cplan = ggml_graph_plan(cond_graph, n_threads);
|
||||
ctx_size += cplan.work_size;
|
||||
|
||||
ctx_size += ggml_used_mem(ctx) + ggml_used_mem_of_data(ctx);
|
||||
@@ -3390,6 +3395,7 @@ class StableDiffusionGGML {
|
||||
// print_ggml_tensor(x_t);
|
||||
struct ggml_tensor* x = ggml_dup_tensor(res_ctx, x_t);
|
||||
copy_ggml_tensor(x, x_t);
|
||||
struct ggml_cplan cplan;
|
||||
|
||||
size_t ctx_size = 10 * 1024 * 1024; // 10MB
|
||||
// calculate the amount of memory required
|
||||
@@ -3417,7 +3423,7 @@ class StableDiffusionGGML {
|
||||
ctx_size += ggml_used_mem(ctx) + ggml_used_mem_of_data(ctx);
|
||||
|
||||
struct ggml_cgraph* diffusion_graph = ggml_build_forward_ctx(ctx, out);
|
||||
struct ggml_cplan cplan = ggml_graph_plan(diffusion_graph, n_threads);
|
||||
cplan = ggml_graph_plan(diffusion_graph, n_threads);
|
||||
|
||||
ctx_size += cplan.work_size;
|
||||
LOG_DEBUG("diffusion context need %.2fMB static memory, with work_size needing %.2fMB",
|
||||
@@ -3449,8 +3455,10 @@ class StableDiffusionGGML {
|
||||
struct ggml_tensor* out = diffusion_model.forward(ctx, noised_input, NULL, context, t_emb);
|
||||
ggml_hold_dynamic_tensor(out);
|
||||
|
||||
struct ggml_cgraph* diffusion_graph = ggml_build_forward_ctx(ctx, out);
|
||||
struct ggml_cplan cplan = ggml_graph_plan(diffusion_graph, n_threads);
|
||||
struct ggml_cgraph* diffusion_graph = ggml_new_graph(ctx);
|
||||
diffusion_graph->order = GGML_CGRAPH_EVAL_ORDER_RIGHT_TO_LEFT;
|
||||
ggml_build_forward_expand(diffusion_graph, out);
|
||||
cplan = ggml_graph_plan(diffusion_graph, n_threads);
|
||||
|
||||
ggml_set_dynamic(ctx, false);
|
||||
struct ggml_tensor* buf = ggml_new_tensor_1d(ctx, GGML_TYPE_I8, cplan.work_size);
|
||||
@@ -3740,7 +3748,7 @@ class StableDiffusionGGML {
|
||||
}
|
||||
} else {
|
||||
// DPM-Solver-2
|
||||
float sigma_mid = exp(0.5 * (log(sigmas[i]) + log(sigmas[i + 1])));
|
||||
float sigma_mid = exp(0.5f * (log(sigmas[i]) + log(sigmas[i + 1])));
|
||||
float dt_1 = sigma_mid - sigmas[i];
|
||||
float dt_2 = sigmas[i + 1] - sigmas[i];
|
||||
|
||||
@@ -3803,7 +3811,7 @@ class StableDiffusionGGML {
|
||||
float t = t_fn(sigmas[i]);
|
||||
float t_next = t_fn(sigma_down);
|
||||
float h = t_next - t;
|
||||
float s = t + 0.5 * h;
|
||||
float s = t + 0.5f * h;
|
||||
|
||||
float* vec_d = (float*)d->data;
|
||||
float* vec_x = (float*)x->data;
|
||||
@@ -3812,7 +3820,7 @@ class StableDiffusionGGML {
|
||||
|
||||
// First half-step
|
||||
for (int j = 0; j < ggml_nelements(x); j++) {
|
||||
vec_x2[j] = (sigma_fn(s) / sigma_fn(t)) * vec_x[j] - (exp(-h * 0.5) - 1) * vec_denoised[j];
|
||||
vec_x2[j] = (sigma_fn(s) / sigma_fn(t)) * vec_x[j] - (exp(-h * 0.5f) - 1) * vec_denoised[j];
|
||||
}
|
||||
|
||||
denoise(x2, sigmas[i + 1], i + 1);
|
||||
@@ -3854,7 +3862,7 @@ class StableDiffusionGGML {
|
||||
float t_next = t_fn(sigmas[i + 1]);
|
||||
float h = t_next - t;
|
||||
float a = sigmas[i + 1] / sigmas[i];
|
||||
float b = exp(-h) - 1.;
|
||||
float b = exp(-h) - 1.f;
|
||||
float* vec_x = (float*)x->data;
|
||||
float* vec_denoised = (float*)denoised->data;
|
||||
float* vec_old_denoised = (float*)old_denoised->data;
|
||||
@@ -3868,7 +3876,7 @@ class StableDiffusionGGML {
|
||||
float h_last = t - t_fn(sigmas[i - 1]);
|
||||
float r = h_last / h;
|
||||
for (int j = 0; j < ggml_nelements(x); j++) {
|
||||
float denoised_d = (1. + 1. / (2. * r)) * vec_denoised[j] - (1. / (2. * r)) * vec_old_denoised[j];
|
||||
float denoised_d = (1.f + 1.f / (2.f * r)) * vec_denoised[j] - (1.f / (2.f * r)) * vec_old_denoised[j];
|
||||
vec_x[j] = a * vec_x[j] - b * denoised_d;
|
||||
}
|
||||
}
|
||||
@@ -3902,7 +3910,7 @@ class StableDiffusionGGML {
|
||||
|
||||
if (i == 0 || sigmas[i + 1] == 0) {
|
||||
// Simpler step for the edge cases
|
||||
float b = exp(-h) - 1.;
|
||||
float b = exp(-h) - 1.f;
|
||||
for (int j = 0; j < ggml_nelements(x); j++) {
|
||||
vec_x[j] = a * vec_x[j] - b * vec_denoised[j];
|
||||
}
|
||||
@@ -3911,10 +3919,10 @@ class StableDiffusionGGML {
|
||||
float h_min = std::min(h_last, h);
|
||||
float h_max = std::max(h_last, h);
|
||||
float r = h_max / h_min;
|
||||
float h_d = (h_max + h_min) / 2.;
|
||||
float b = exp(-h_d) - 1.;
|
||||
float h_d = (h_max + h_min) / 2.f;
|
||||
float b = exp(-h_d) - 1.f;
|
||||
for (int j = 0; j < ggml_nelements(x); j++) {
|
||||
float denoised_d = (1. + 1. / (2. * r)) * vec_denoised[j] - (1. / (2. * r)) * vec_old_denoised[j];
|
||||
float denoised_d = (1.f + 1.f / (2.f * r)) * vec_denoised[j] - (1.f / (2.f * r)) * vec_old_denoised[j];
|
||||
vec_x[j] = a * vec_x[j] - b * denoised_d;
|
||||
}
|
||||
}
|
||||
@@ -3961,6 +3969,7 @@ class StableDiffusionGGML {
|
||||
int64_t W = x->ne[0];
|
||||
int64_t H = x->ne[1];
|
||||
struct ggml_tensor* result = NULL;
|
||||
struct ggml_cplan cplan;
|
||||
|
||||
// calculate the amount of memory required
|
||||
size_t ctx_size = 10 * 1024 * 1024; // 10MB
|
||||
@@ -3981,7 +3990,7 @@ class StableDiffusionGGML {
|
||||
ctx_size += ggml_used_mem(ctx) + ggml_used_mem_of_data(ctx);
|
||||
|
||||
struct ggml_cgraph* vae_graph = ggml_build_forward_ctx(ctx, moments);
|
||||
struct ggml_cplan cplan = ggml_graph_plan(vae_graph, n_threads);
|
||||
cplan = ggml_graph_plan(vae_graph, n_threads);
|
||||
|
||||
ctx_size += cplan.work_size;
|
||||
LOG_DEBUG("vae context need %.2fMB static memory, with work_size needing %.2fMB",
|
||||
@@ -4005,7 +4014,10 @@ class StableDiffusionGGML {
|
||||
}
|
||||
|
||||
struct ggml_tensor* moments = first_stage_model.encode(ctx, x);
|
||||
struct ggml_cgraph* vae_graph = ggml_build_forward_ctx(ctx, moments);
|
||||
|
||||
struct ggml_cgraph* vae_graph = ggml_new_graph(ctx);
|
||||
vae_graph->order = GGML_CGRAPH_EVAL_ORDER_RIGHT_TO_LEFT;
|
||||
ggml_build_forward_expand(vae_graph, moments);
|
||||
|
||||
int64_t t0 = ggml_time_ms();
|
||||
ggml_graph_compute_with_ctx(ctx, vae_graph, n_threads);
|
||||
@@ -4083,6 +4095,7 @@ class StableDiffusionGGML {
|
||||
int64_t W = z->ne[0];
|
||||
int64_t H = z->ne[1];
|
||||
struct ggml_tensor* result_img = NULL;
|
||||
struct ggml_cplan cplan;
|
||||
|
||||
{
|
||||
float* vec = (float*)z->data;
|
||||
@@ -4110,7 +4123,7 @@ class StableDiffusionGGML {
|
||||
ctx_size += ggml_used_mem(ctx) + ggml_used_mem_of_data(ctx);
|
||||
|
||||
struct ggml_cgraph* vae_graph = ggml_build_forward_ctx(ctx, img);
|
||||
struct ggml_cplan cplan = ggml_graph_plan(vae_graph, n_threads);
|
||||
cplan = ggml_graph_plan(vae_graph, n_threads);
|
||||
|
||||
ctx_size += cplan.work_size;
|
||||
LOG_DEBUG("vae context need %.2fMB static memory, with work_size needing %.2fMB",
|
||||
@@ -4134,7 +4147,10 @@ class StableDiffusionGGML {
|
||||
}
|
||||
|
||||
struct ggml_tensor* img = first_stage_model.decode(ctx, z);
|
||||
struct ggml_cgraph* vae_graph = ggml_build_forward_ctx(ctx, img);
|
||||
|
||||
struct ggml_cgraph* vae_graph = ggml_new_graph(ctx);
|
||||
vae_graph->order = GGML_CGRAPH_EVAL_ORDER_RIGHT_TO_LEFT;
|
||||
ggml_build_forward_expand(vae_graph, img);
|
||||
|
||||
int64_t t0 = ggml_time_ms();
|
||||
ggml_graph_compute_with_ctx(ctx, vae_graph, n_threads);
|
||||
|
||||
Reference in New Issue
Block a user