mirror of
https://github.com/leejet/stable-diffusion.cpp.git
synced 2026-11-11 19:36:33 +00:00
perf: cache CPU position embeddings across DiT runners (#2211)
This commit is contained in:
1 parent
a85db96aa5
commit
ea209dbfcf
31 files changed
+855
-610
No files matched your search
@@ -9,6 +9,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "core/pe_cache.h"
|
||||
|
||||
#include "core/ggml_extend.h"
|
||||
#include "core/ggml_runner.h"
|
||||
@@ -473,20 +474,9 @@ namespace MiniT2I {
|
||||
};
|
||||
|
||||
struct MiniT2IRunner : public DiffusionModelRunner {
|
||||
sd::PECache pe_cache_;
|
||||
MiniT2IConfig config;
|
||||
MMJiT model;
|
||||
ggml_context* position_cache_ctx = nullptr;
|
||||
ggml_backend_buffer_t position_cache_buffer = nullptr;
|
||||
ggml_tensor* cached_pos_embed = nullptr;
|
||||
ggml_tensor* cached_txt_pe = nullptr;
|
||||
ggml_tensor* cached_joint_pe = nullptr;
|
||||
int64_t cached_img_side = -1;
|
||||
int64_t cached_txt_len = -1;
|
||||
int64_t cached_hidden_size = -1;
|
||||
int64_t cached_head_dim = -1;
|
||||
bool cached_circular_x = false;
|
||||
bool cached_circular_y = false;
|
||||
|
||||
MiniT2IRunner(ggml_backend_t backend,
|
||||
const String2TensorStorage& tensor_storage_map = {},
|
||||
const std::string prefix = "",
|
||||
@@ -497,10 +487,6 @@ namespace MiniT2I {
|
||||
model.init(params_ctx, tensor_storage_map, this->prefix);
|
||||
}
|
||||
|
||||
~MiniT2IRunner() override {
|
||||
free_position_cache();
|
||||
}
|
||||
|
||||
std::string get_desc() override {
|
||||
return "MiniT2I";
|
||||
}
|
||||
@@ -509,75 +495,6 @@ namespace MiniT2I {
|
||||
model.get_param_tensors(tensors, prefix);
|
||||
}
|
||||
|
||||
void free_position_cache() {
|
||||
if (position_cache_buffer != nullptr) {
|
||||
ggml_backend_buffer_free(position_cache_buffer);
|
||||
position_cache_buffer = nullptr;
|
||||
}
|
||||
if (position_cache_ctx != nullptr) {
|
||||
ggml_free(position_cache_ctx);
|
||||
position_cache_ctx = nullptr;
|
||||
}
|
||||
cached_pos_embed = nullptr;
|
||||
cached_txt_pe = nullptr;
|
||||
cached_joint_pe = nullptr;
|
||||
cached_img_side = -1;
|
||||
cached_txt_len = -1;
|
||||
cached_hidden_size = -1;
|
||||
cached_head_dim = -1;
|
||||
}
|
||||
|
||||
void ensure_position_cache(int64_t img_side, int64_t txt_len) {
|
||||
if (cached_img_side == img_side &&
|
||||
cached_txt_len == txt_len &&
|
||||
cached_hidden_size == config.hidden_size &&
|
||||
cached_head_dim == config.head_dim &&
|
||||
cached_circular_x == circular_x_enabled &&
|
||||
cached_circular_y == circular_y_enabled &&
|
||||
cached_pos_embed != nullptr &&
|
||||
cached_txt_pe != nullptr &&
|
||||
cached_joint_pe != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
free_position_cache();
|
||||
|
||||
auto pos_embed_vec = make_2d_sincos_pos_embed(static_cast<int>(img_side), static_cast<int>(config.hidden_size));
|
||||
auto txt_pe_vec = make_text_rope(static_cast<int>(txt_len), static_cast<int>(config.head_dim));
|
||||
auto img_pe_vec = finish_rope_pe(make_vision_rope(static_cast<int>(img_side), static_cast<int>(config.head_dim)));
|
||||
auto joint_pe_vec = txt_pe_vec;
|
||||
joint_pe_vec.insert(joint_pe_vec.end(), img_pe_vec.begin(), img_pe_vec.end());
|
||||
|
||||
ggml_init_params params;
|
||||
params.mem_size = static_cast<size_t>(3 * ggml_tensor_overhead());
|
||||
params.mem_buffer = nullptr;
|
||||
params.no_alloc = true;
|
||||
position_cache_ctx = ggml_init(params);
|
||||
GGML_ASSERT(position_cache_ctx != nullptr);
|
||||
|
||||
cached_pos_embed = ggml_new_tensor_3d(position_cache_ctx, GGML_TYPE_F32, config.hidden_size, img_side * img_side, 1);
|
||||
ggml_set_name(cached_pos_embed, "minit2i.pos_embed");
|
||||
cached_txt_pe = ggml_new_tensor_4d(position_cache_ctx, GGML_TYPE_F32, 2, 2, config.head_dim / 2, txt_len);
|
||||
ggml_set_name(cached_txt_pe, "minit2i.txt_pe");
|
||||
cached_joint_pe = ggml_new_tensor_4d(position_cache_ctx, GGML_TYPE_F32, 2, 2, config.head_dim / 2, txt_len + img_side * img_side);
|
||||
ggml_set_name(cached_joint_pe, "minit2i.joint_pe");
|
||||
|
||||
position_cache_buffer = ggml_backend_alloc_ctx_tensors(position_cache_ctx, runtime_backend);
|
||||
GGML_ASSERT(position_cache_buffer != nullptr);
|
||||
ggml_backend_buffer_set_usage(position_cache_buffer, GGML_BACKEND_BUFFER_USAGE_WEIGHTS);
|
||||
ggml_backend_tensor_set(cached_pos_embed, pos_embed_vec.data(), 0, ggml_nbytes(cached_pos_embed));
|
||||
ggml_backend_tensor_set(cached_txt_pe, txt_pe_vec.data(), 0, ggml_nbytes(cached_txt_pe));
|
||||
ggml_backend_tensor_set(cached_joint_pe, joint_pe_vec.data(), 0, ggml_nbytes(cached_joint_pe));
|
||||
ggml_backend_synchronize(runtime_backend);
|
||||
|
||||
cached_img_side = img_side;
|
||||
cached_txt_len = txt_len;
|
||||
cached_hidden_size = config.hidden_size;
|
||||
cached_head_dim = config.head_dim;
|
||||
cached_circular_x = circular_x_enabled;
|
||||
cached_circular_y = circular_y_enabled;
|
||||
}
|
||||
|
||||
ggml_cgraph* build_graph(const sd::Tensor<float>& x_tensor,
|
||||
const sd::Tensor<float>& timesteps_tensor,
|
||||
const sd::Tensor<float>& context_tensor,
|
||||
@@ -592,10 +509,29 @@ namespace MiniT2I {
|
||||
int64_t H = x->ne[1];
|
||||
int64_t img_side = H / config.patch_size;
|
||||
int64_t txt_len = context->ne[1];
|
||||
ensure_position_cache(img_side, txt_len);
|
||||
sd::PECacheKey pos_key("minit2i.pos_embed");
|
||||
pos_key.add(img_side).add(config.hidden_size);
|
||||
auto pos_embed = make_input(pe_cache_.get_or_create(pos_key, [&]() {
|
||||
return sd::Tensor<float>({config.hidden_size, img_side * img_side, 1},
|
||||
make_2d_sincos_pos_embed(static_cast<int>(img_side), static_cast<int>(config.hidden_size)));
|
||||
}));
|
||||
sd::PECacheKey txt_key("minit2i.txt_pe");
|
||||
txt_key.add(txt_len).add(config.head_dim);
|
||||
auto txt_pe = make_input(pe_cache_.get_or_create(txt_key, [&]() {
|
||||
return sd::Tensor<float>({2, 2, config.head_dim / 2, txt_len},
|
||||
make_text_rope(static_cast<int>(txt_len), static_cast<int>(config.head_dim)));
|
||||
}));
|
||||
sd::PECacheKey joint_key("minit2i.joint_pe");
|
||||
joint_key.add(img_side).add(txt_len).add(config.head_dim).add(circular_x_enabled).add(circular_y_enabled);
|
||||
auto joint_pe = make_input(pe_cache_.get_or_create(joint_key, [&]() {
|
||||
auto values = make_text_rope(static_cast<int>(txt_len), static_cast<int>(config.head_dim));
|
||||
auto image = finish_rope_pe(make_vision_rope(static_cast<int>(img_side), static_cast<int>(config.head_dim)));
|
||||
values.insert(values.end(), image.begin(), image.end());
|
||||
return sd::Tensor<float>({2, 2, config.head_dim / 2, txt_len + img_side * img_side}, std::move(values));
|
||||
}));
|
||||
|
||||
auto runner_ctx = get_context();
|
||||
auto out = model.forward(&runner_ctx, x, context, mask, cached_pos_embed, cached_txt_pe, cached_joint_pe);
|
||||
auto out = model.forward(&runner_ctx, x, context, mask, pos_embed, txt_pe, joint_pe);
|
||||
ggml_build_forward_expand(gf, out);
|
||||
return gf;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user