mirror of
https://github.com/leejet/stable-diffusion.cpp.git
synced 2026-11-11 03:24:30 +00:00
feat: add native CUDA SageAttention support (#2005)
This commit is contained in:
1 parent
15f335daa5
commit
187b2561ea
13 files changed
+176
-5
No files matched your search
@@ -622,7 +622,8 @@ ggml_tensor* ggml_ext_attention_ext(ggml_context* ctx,
|
||||
ggml_tensor* mask,
|
||||
bool skip_reshape,
|
||||
bool flash_attn,
|
||||
float kv_scale) { // avoid overflow
|
||||
float kv_scale,
|
||||
bool sage_attn) { // avoid overflow
|
||||
int64_t L_q;
|
||||
int64_t L_k;
|
||||
int64_t C;
|
||||
@@ -713,7 +714,37 @@ ggml_tensor* ggml_ext_attention_ext(ggml_context* ctx,
|
||||
return out;
|
||||
};
|
||||
|
||||
if (flash_attn) {
|
||||
#ifndef SD_USE_UPSTREAM_GGML
|
||||
if (sage_attn && mask == nullptr && d_head > 0 && d_head <= 128) {
|
||||
auto q_in = ggml_reshape_4d(ctx, ggml_ext_cont(ctx, q->type == GGML_TYPE_F32 ? q : ggml_cast(ctx, q, GGML_TYPE_F32)), d_head, L_q, n_head, N);
|
||||
auto k_in = ggml_reshape_4d(ctx, ggml_ext_cont(ctx, k->type == GGML_TYPE_F32 ? k : ggml_cast(ctx, k, GGML_TYPE_F32)), d_head, L_k, n_kv_head, N);
|
||||
auto v_in = ggml_ext_cont(ctx, ggml_permute(ctx, v, 0, 2, 1, 3));
|
||||
const int64_t padded_head = d_head <= 64 ? 64 : 128;
|
||||
if ((padded_head != d_head || kv_scale != 1.0f) && v_in->type != GGML_TYPE_F32) {
|
||||
v_in = ggml_cast(ctx, v_in, GGML_TYPE_F32);
|
||||
}
|
||||
if (padded_head != d_head) {
|
||||
// Keep the original head's softmax scale when padding for the CUDA kernel.
|
||||
q_in = ggml_pad(ctx, q_in, padded_head - d_head, 0, 0, 0);
|
||||
k_in = ggml_pad(ctx, k_in, padded_head - d_head, 0, 0, 0);
|
||||
v_in = ggml_pad(ctx, v_in, padded_head - d_head, 0, 0, 0);
|
||||
}
|
||||
if (kv_scale != 1.0f) {
|
||||
k_in = ggml_ext_scale(ctx, k_in, kv_scale);
|
||||
v_in = ggml_ext_scale(ctx, v_in, kv_scale);
|
||||
}
|
||||
v_in = ggml_cast(ctx, v_in, GGML_TYPE_F16);
|
||||
auto out = ggml_sage_attn(ctx, q_in, k_in, v_in, scale / kv_scale, GGML_SAGE_ATTN_AUTO);
|
||||
if (ggml_backend_supports_op(backend, out)) {
|
||||
kqv = kv_scale != 1.0f ? ggml_ext_scale(ctx, out, 1.0f / kv_scale) : out;
|
||||
if (padded_head != d_head) {
|
||||
kqv = ggml_ext_slice(ctx, kqv, 0, 0, d_head);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (kqv == nullptr && (flash_attn || sage_attn)) {
|
||||
// LOG_VERBOSE("attention_ext L_q:%d L_k:%d n_head:%d C:%d d_head:%d N:%d", L_q, L_k, n_head, C, d_head, N);
|
||||
bool can_use_flash_attn = true;
|
||||
if (mask != nullptr) {
|
||||
|
||||
@@ -220,7 +220,8 @@ ggml_tensor* ggml_ext_attention_ext(ggml_context* ctx,
|
||||
ggml_tensor* mask = nullptr,
|
||||
bool skip_reshape = false,
|
||||
bool flash_attn = false,
|
||||
float kv_scale = 1.0f);
|
||||
float kv_scale = 1.0f,
|
||||
bool sage_attn = false);
|
||||
|
||||
ggml_tensor* ggml_ext_layer_norm(ggml_context* ctx,
|
||||
ggml_tensor* x,
|
||||
|
||||
@@ -25,7 +25,7 @@ ggml_tensor* ggml_ext_attention_ext(GGMLRunnerContext* ctx,
|
||||
if (ctx->attn_scale > 0.f) {
|
||||
kv_scale = ctx->attn_scale;
|
||||
}
|
||||
return ggml_ext_attention_ext(ctx->ggml_ctx, ctx->backend, q, k, v, n_head, mask, skip_reshape, flash_attn, kv_scale);
|
||||
return ggml_ext_attention_ext(ctx->ggml_ctx, ctx->backend, q, k, v, n_head, mask, skip_reshape, flash_attn, kv_scale, ctx->sage_attn_enabled);
|
||||
}
|
||||
|
||||
void GGMLRunner::alloc_params_ctx() {
|
||||
@@ -520,6 +520,7 @@ GGMLRunnerContext GGMLRunner::get_context() {
|
||||
runner_ctx.ggml_ctx = compute_ctx;
|
||||
runner_ctx.backend = runtime_backend;
|
||||
runner_ctx.flash_attn_enabled = flash_attn_enabled;
|
||||
runner_ctx.sage_attn_enabled = sage_attn_enabled;
|
||||
runner_ctx.linear_scale = linear_scale;
|
||||
runner_ctx.attn_scale = attn_scale;
|
||||
runner_ctx.conv2d_direct_enabled = conv2d_direct_enabled;
|
||||
|
||||
@@ -68,6 +68,7 @@ struct GGMLRunnerContext {
|
||||
ggml_backend_t backend = nullptr;
|
||||
ggml_context* ggml_ctx = nullptr;
|
||||
bool flash_attn_enabled = false;
|
||||
bool sage_attn_enabled = false;
|
||||
float linear_scale = 0.f;
|
||||
float attn_scale = 0.f;
|
||||
bool conv2d_direct_enabled = false;
|
||||
@@ -176,6 +177,7 @@ protected:
|
||||
const std::string final_result_name = "ggml_runner_final_result_tensor";
|
||||
|
||||
bool flash_attn_enabled = false;
|
||||
bool sage_attn_enabled = false;
|
||||
float linear_scale = 0.f;
|
||||
float attn_scale = 0.f;
|
||||
bool conv2d_direct_enabled = false;
|
||||
@@ -337,6 +339,14 @@ public:
|
||||
flash_attn_enabled = enabled;
|
||||
}
|
||||
|
||||
void set_sage_attention_enabled(bool enabled) {
|
||||
if (sage_attn_enabled != enabled) {
|
||||
free_cache_ctx_and_buffer();
|
||||
graph_cut_plan_cache_.graph_cut_plans.clear();
|
||||
sage_attn_enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
void set_scale_overrides(float linear_scale, float attn_scale) {
|
||||
this->linear_scale = linear_scale;
|
||||
this->attn_scale = attn_scale;
|
||||
|
||||
@@ -858,6 +858,47 @@ bool StableDiffusionGGML::init_model_loader(ModelLoader& model_loader, ModelConf
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StableDiffusionGGML::set_sage_attention_enabled(bool enabled) {
|
||||
if (!diffusion_model) {
|
||||
return false;
|
||||
}
|
||||
if (enabled) {
|
||||
#ifndef SD_USE_UPSTREAM_GGML
|
||||
auto* ctx = ggml_init({4 * ggml_tensor_overhead(), nullptr, true});
|
||||
if (ctx == nullptr) {
|
||||
return false;
|
||||
}
|
||||
auto* q = ggml_new_tensor_4d(ctx, GGML_TYPE_F32, 128, 128, 1, 1);
|
||||
auto* k = ggml_new_tensor_4d(ctx, GGML_TYPE_F32, 128, 128, 1, 1);
|
||||
auto* v = ggml_new_tensor_4d(ctx, GGML_TYPE_F16, 128, 128, 1, 1);
|
||||
auto* op = ggml_sage_attn(ctx, q, k, v, 1.f / sqrtf(128.f), GGML_SAGE_ATTN_AUTO);
|
||||
bool supported = true;
|
||||
for (auto backend : backend_manager.runtime_backends(SDBackendModule::DIFFUSION)) {
|
||||
if (!ggml_backend_supports_op(backend, op)) {
|
||||
LOG_ERROR("SageAttention is unavailable on %s; it requires patched GGML, CUDA Toolkit 12.0 or newer, and SM80 or newer kernels",
|
||||
ggml_backend_name(backend));
|
||||
supported = false;
|
||||
}
|
||||
}
|
||||
ggml_free(ctx);
|
||||
if (!supported) {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
LOG_ERROR("SageAttention requires -DSD_USE_UPSTREAM_GGML=OFF and a CUDA backend");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
diffusion_model->set_sage_attention_enabled(enabled);
|
||||
if (high_noise_diffusion_model) {
|
||||
high_noise_diffusion_model->set_sage_attention_enabled(enabled);
|
||||
}
|
||||
if (enabled) {
|
||||
LOG_INFO("Using SageAttention in the diffusion model; CUDA selects the supported kernel, unsupported layers use flash/default attention");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StableDiffusionGGML::init(const sd_ctx_params_t* sd_ctx_params) {
|
||||
#ifdef SD_USE_UPSTREAM_GGML
|
||||
LOG_WARN(
|
||||
@@ -1136,6 +1177,9 @@ bool StableDiffusionGGML::validate_and_load_runners() {
|
||||
high_noise_diffusion_model->set_flash_attention_enabled(true);
|
||||
}
|
||||
}
|
||||
if (sd_ctx_params->sage_attn && !set_sage_attention_enabled(true)) {
|
||||
return false;
|
||||
}
|
||||
LOG_VERBOSE("validating model metadata");
|
||||
|
||||
std::set<std::string> ignore_tensors;
|
||||
|
||||
@@ -312,6 +312,7 @@ public:
|
||||
bool init_model_loader(ModelLoader& model_loader, ModelConfig& configuration);
|
||||
|
||||
bool init(const sd_ctx_params_t* sd_ctx_params);
|
||||
bool set_sage_attention_enabled(bool enabled);
|
||||
|
||||
bool uses_tae() const;
|
||||
|
||||
|
||||
@@ -337,6 +337,7 @@ void sd_ctx_params_init(sd_ctx_params_t* sd_ctx_params) {
|
||||
sd_ctx_params->eager_load = false;
|
||||
sd_ctx_params->enable_mmap = false;
|
||||
sd_ctx_params->diffusion_flash_attn = false;
|
||||
sd_ctx_params->sage_attn = false;
|
||||
sd_ctx_params->linear_scale = 0.f;
|
||||
sd_ctx_params->attn_scale = 0.f;
|
||||
sd_ctx_params->vae_format = SD_VAE_FORMAT_AUTO;
|
||||
@@ -392,6 +393,7 @@ char* sd_ctx_params_to_str(const sd_ctx_params_t* sd_ctx_params) {
|
||||
"auto_fit: %s\n"
|
||||
"flash_attn: %s\n"
|
||||
"diffusion_flash_attn: %s\n"
|
||||
"sage_attn: %s\n"
|
||||
"linear_scale: %g\n"
|
||||
"attn_scale: %g\n"
|
||||
"vae_format: %s\n",
|
||||
@@ -431,6 +433,7 @@ char* sd_ctx_params_to_str(const sd_ctx_params_t* sd_ctx_params) {
|
||||
BOOL_STR(sd_ctx_params->auto_fit),
|
||||
BOOL_STR(sd_ctx_params->flash_attn),
|
||||
BOOL_STR(sd_ctx_params->diffusion_flash_attn),
|
||||
BOOL_STR(sd_ctx_params->sage_attn),
|
||||
sd_ctx_params->linear_scale,
|
||||
sd_ctx_params->attn_scale,
|
||||
sd_vae_format_name(sd_ctx_params->vae_format));
|
||||
|
||||
Reference in new issue
Block a user