apply workspace support for KV cache
This commit is contained in:
parent
ed403dca27
commit
3d73312d9d
|
|
@ -2596,6 +2596,32 @@ void common_speculative_print_stats(const common_speculative * spec, double slot
|
|||
const double kv_upload_total_ms = kv_upload_feature_ms + kv_upload_pos_ms;
|
||||
const double kv_compute_ms = (double) graph_stats.graph_kv_cache_compute_us / 1000.0;
|
||||
const double kv_sync_ms = (double) graph_stats.graph_kv_cache_sync_us / 1000.0;
|
||||
const double kv_workspace_total_ms = (double) (
|
||||
graph_stats.graph_kv_workspace_build_us +
|
||||
graph_stats.graph_kv_workspace_reserve_us +
|
||||
graph_stats.graph_kv_workspace_reset_us +
|
||||
graph_stats.graph_kv_workspace_alloc_us +
|
||||
graph_stats.graph_kv_workspace_compute_us +
|
||||
graph_stats.graph_kv_workspace_sync_us) / 1000.0;
|
||||
const double draft_kv_traffic_ms = (double) (
|
||||
graph_stats.graph_main_node_k_ctx_view_us +
|
||||
graph_stats.graph_main_node_v_ctx_view_us +
|
||||
graph_stats.graph_main_node_k_concat_us +
|
||||
graph_stats.graph_main_node_v_concat_us +
|
||||
graph_stats.graph_main_node_k_pad_us +
|
||||
graph_stats.graph_main_node_v_pad_us +
|
||||
graph_stats.graph_main_node_k_perm_cont_us +
|
||||
graph_stats.graph_main_node_v_perm_cont_us) / 1000.0;
|
||||
const double draft_main_profiled_ms = (double) (
|
||||
graph_stats.graph_main_node_qcur_us +
|
||||
graph_stats.graph_main_node_k_draft_us +
|
||||
graph_stats.graph_main_node_v_draft_us +
|
||||
graph_stats.graph_main_node_flash_attn_us +
|
||||
graph_stats.graph_main_node_attn_out_us +
|
||||
graph_stats.graph_main_node_ffn_us +
|
||||
graph_stats.graph_main_node_result_rows_us +
|
||||
graph_stats.graph_main_node_result_norm_us +
|
||||
graph_stats.graph_main_node_result_us) / 1000.0;
|
||||
const double replay_append_ms = (double) dflash_state->t_accept_append_us / 1000.0;
|
||||
const double feature_path_ms = (double) (
|
||||
capture_stats.capture_prepare_sync_us +
|
||||
|
|
@ -2704,6 +2730,18 @@ void common_speculative_print_stats(const common_speculative * spec, double slot
|
|||
(unsigned long long) graph_stats.graph_kv_cache_cached_bytes,
|
||||
graph_stats.last_kv_cache_host_layers);
|
||||
|
||||
if (graph_stats.graph_kv_workspace_calls > 0) {
|
||||
LOG_INF("statistics dflash kv workspace: total=%.3f ms build/reserve/reset/alloc/compute/sync=%.3f/%.3f/%.3f/%.3f/%.3f/%.3f ms calls=%llu\n",
|
||||
kv_workspace_total_ms,
|
||||
(double) graph_stats.graph_kv_workspace_build_us / 1000.0,
|
||||
(double) graph_stats.graph_kv_workspace_reserve_us / 1000.0,
|
||||
(double) graph_stats.graph_kv_workspace_reset_us / 1000.0,
|
||||
(double) graph_stats.graph_kv_workspace_alloc_us / 1000.0,
|
||||
(double) graph_stats.graph_kv_workspace_compute_us / 1000.0,
|
||||
(double) graph_stats.graph_kv_workspace_sync_us / 1000.0,
|
||||
(unsigned long long) graph_stats.graph_kv_workspace_calls);
|
||||
}
|
||||
|
||||
if (graph_stats.decode_internal_chunks > 0) {
|
||||
LOG_INF("statistics dflash decode: llama_decode(total)=%.3f ms calls=%zu chunks=%llu rebuilds=%llu sync_points=%llu internal(total/prelude/sched_reset/build/alloc/prepare/set_inputs/compute/get_result/get_embedding/final_reset)=%.3f/%.3f/%.3f/%.3f/%.3f/%.3f/%.3f/%.3f/%.3f/%.3f/%.3f ms\n",
|
||||
(double) dflash_state->t_draft_decode_us / 1000.0,
|
||||
|
|
@ -2748,6 +2786,67 @@ void common_speculative_print_stats(const common_speculative * spec, double slot
|
|||
(unsigned long long) graph_stats.graph_kv_node_v_store_calls);
|
||||
}
|
||||
|
||||
if (graph_stats.graph_main_node_qcur_calls > 0 ||
|
||||
graph_stats.graph_main_node_k_draft_calls > 0 ||
|
||||
graph_stats.graph_main_node_v_draft_calls > 0 ||
|
||||
graph_stats.graph_main_node_flash_attn_calls > 0 ||
|
||||
graph_stats.graph_main_node_attn_out_calls > 0 ||
|
||||
graph_stats.graph_main_node_ffn_calls > 0 ||
|
||||
graph_stats.graph_main_node_result_rows_calls > 0 ||
|
||||
graph_stats.graph_main_node_result_norm_calls > 0 ||
|
||||
graph_stats.graph_main_node_result_calls > 0) {
|
||||
LOG_INF("statistics dflash draft nodes: profiled=%.3f ms graph_compute=%.3f ms qcur/k_draft/v_draft/flash_attn/attn_out/ffn/result_rows/result_norm/result=%.3f/%.3f/%.3f/%.3f/%.3f/%.3f/%.3f/%.3f/%.3f ms calls=%llu/%llu/%llu/%llu/%llu/%llu/%llu/%llu/%llu\n",
|
||||
draft_main_profiled_ms,
|
||||
(double) graph_stats.decode_graph_compute_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_qcur_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_k_draft_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_v_draft_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_flash_attn_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_attn_out_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_ffn_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_result_rows_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_result_norm_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_result_us / 1000.0,
|
||||
(unsigned long long) graph_stats.graph_main_node_qcur_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_k_draft_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_v_draft_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_flash_attn_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_attn_out_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_ffn_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_result_rows_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_result_norm_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_result_calls);
|
||||
}
|
||||
|
||||
if (graph_stats.graph_main_node_k_ctx_view_calls > 0 ||
|
||||
graph_stats.graph_main_node_v_ctx_view_calls > 0 ||
|
||||
graph_stats.graph_main_node_k_concat_calls > 0 ||
|
||||
graph_stats.graph_main_node_v_concat_calls > 0 ||
|
||||
graph_stats.graph_main_node_k_pad_calls > 0 ||
|
||||
graph_stats.graph_main_node_v_pad_calls > 0 ||
|
||||
graph_stats.graph_main_node_k_perm_cont_calls > 0 ||
|
||||
graph_stats.graph_main_node_v_perm_cont_calls > 0) {
|
||||
LOG_INF("statistics dflash draft kv traffic: total=%.3f ms graph_compute=%.3f ms k_ctx_view/v_ctx_view/k_concat/v_concat/k_pad/v_pad/k_perm_cont/v_perm_cont=%.3f/%.3f/%.3f/%.3f/%.3f/%.3f/%.3f/%.3f ms calls=%llu/%llu/%llu/%llu/%llu/%llu/%llu/%llu\n",
|
||||
draft_kv_traffic_ms,
|
||||
(double) graph_stats.decode_graph_compute_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_k_ctx_view_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_v_ctx_view_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_k_concat_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_v_concat_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_k_pad_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_v_pad_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_k_perm_cont_us / 1000.0,
|
||||
(double) graph_stats.graph_main_node_v_perm_cont_us / 1000.0,
|
||||
(unsigned long long) graph_stats.graph_main_node_k_ctx_view_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_v_ctx_view_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_k_concat_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_v_concat_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_k_pad_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_v_pad_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_k_perm_cont_calls,
|
||||
(unsigned long long) graph_stats.graph_main_node_v_perm_cont_calls);
|
||||
}
|
||||
|
||||
LOG_INF("statistics dflash hot: kv(upload_f/upload_p/upload/compute/sync)=%.3f/%.3f/%.3f/%.3f/%.3f ms calls=%llu replay(accepted_prefix_append)=%.3f ms calls=%zu rows=%zu\n",
|
||||
kv_upload_feature_ms,
|
||||
kv_upload_pos_ms,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,119 @@ static bool dflash_use_kv_cache_experiment() {
|
|||
std::strcmp(env, "off") != 0;
|
||||
}
|
||||
|
||||
static bool dflash_use_kv_workspace_experiment() {
|
||||
const char * env = std::getenv("IK_DFLASH_KV_WORKSPACE");
|
||||
if (env == nullptr || *env == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::strcmp(env, "0") != 0 &&
|
||||
std::strcmp(env, "false") != 0 &&
|
||||
std::strcmp(env, "off") != 0;
|
||||
}
|
||||
|
||||
ggml_cgraph * llm_build_context::build_dflash_kv_workspace() {
|
||||
const int64_t n_embd_head_k = hparams.n_embd_head_k(0);
|
||||
const int64_t n_embd_head_v = hparams.n_embd_head_v(0);
|
||||
const int64_t ctx_len = lctx.dflash_visible_cross_ctx > 0
|
||||
? (int64_t) lctx.dflash_visible_cross_ctx
|
||||
: std::max<int64_t>(1, (int64_t) cparams.n_ctx - (int64_t) hparams.dflash_block_size);
|
||||
const int32_t cache_rows = std::clamp(lctx.dflash_kv_cache_view_n_filled, 0, (int32_t) ctx_len);
|
||||
const int32_t cache_write_pos = ctx_len > 0
|
||||
? ((lctx.dflash_kv_cache_view_write_pos % (int32_t) ctx_len) + (int32_t) ctx_len) % (int32_t) ctx_len
|
||||
: 0;
|
||||
|
||||
GGML_ASSERT(n_embd_head_k == n_embd_head_v);
|
||||
GGML_ASSERT(lctx.ensure_dflash_kv_cache_tensors((int32_t) ctx_len));
|
||||
GGML_ASSERT((int32_t) lctx.dflash_k_ctx_workspace.size() == n_layer);
|
||||
GGML_ASSERT((int32_t) lctx.dflash_v_ctx_workspace.size() == n_layer);
|
||||
|
||||
ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes((int) std::max<int64_t>(1, ctx_len)) + 16 * n_layer, false);
|
||||
|
||||
auto build_ordered_cache_view = [&](ggml_tensor * cache) -> ggml_tensor * {
|
||||
if (!lctx.dflash_kv_cache_view_valid || cache_rows <= 0) {
|
||||
return cache;
|
||||
}
|
||||
|
||||
if (cache_rows < ctx_len) {
|
||||
ggml_tensor * zero_pad = ggml_view_3d(ctx0, cache,
|
||||
cache->ne[0],
|
||||
cache->ne[1],
|
||||
ctx_len - cache_rows,
|
||||
cache->nb[1],
|
||||
cache->nb[2],
|
||||
(size_t) cache_rows * cache->nb[2]);
|
||||
ggml_tensor * valid = ggml_view_3d(ctx0, cache,
|
||||
cache->ne[0],
|
||||
cache->ne[1],
|
||||
cache_rows,
|
||||
cache->nb[1],
|
||||
cache->nb[2],
|
||||
0);
|
||||
return ggml_concat(ctx0, zero_pad, valid, 2);
|
||||
}
|
||||
|
||||
if (cache_write_pos == 0) {
|
||||
return cache;
|
||||
}
|
||||
|
||||
ggml_tensor * tail = ggml_view_3d(ctx0, cache,
|
||||
cache->ne[0],
|
||||
cache->ne[1],
|
||||
ctx_len - cache_write_pos,
|
||||
cache->nb[1],
|
||||
cache->nb[2],
|
||||
(size_t) cache_write_pos * cache->nb[2]);
|
||||
ggml_tensor * head = ggml_view_3d(ctx0, cache,
|
||||
cache->ne[0],
|
||||
cache->ne[1],
|
||||
cache_write_pos,
|
||||
cache->nb[1],
|
||||
cache->nb[2],
|
||||
0);
|
||||
return ggml_concat(ctx0, tail, head, 2);
|
||||
};
|
||||
|
||||
for (int il = 0; il < n_layer; ++il) {
|
||||
GGML_ASSERT((size_t) il < lctx.dflash_k_ctx_cache.size());
|
||||
GGML_ASSERT((size_t) il < lctx.dflash_v_ctx_cache.size());
|
||||
|
||||
ggml_tensor * Kordered = build_ordered_cache_view(lctx.dflash_k_ctx_cache[(size_t) il]);
|
||||
ggml_tensor * Vordered = build_ordered_cache_view(lctx.dflash_v_ctx_cache[(size_t) il]);
|
||||
cb(Kordered, "dflash_workspace_k_ctx_view", il);
|
||||
cb(Vordered, "dflash_workspace_v_ctx_view", il);
|
||||
|
||||
ggml_tensor * Kworkspace = ggml_cont(ctx0, ggml_permute(ctx0, Kordered, 0, 2, 1, 3));
|
||||
ggml_tensor * Vworkspace = ggml_cont(ctx0, ggml_permute(ctx0, Vordered, 0, 2, 1, 3));
|
||||
cb(Kworkspace, "dflash_workspace_k_perm_cont", il);
|
||||
cb(Vworkspace, "dflash_workspace_v_perm_cont", il);
|
||||
|
||||
ggml_tensor * Kdst = ggml_view_3d(ctx0, lctx.dflash_k_ctx_workspace[(size_t) il],
|
||||
lctx.dflash_k_ctx_workspace[(size_t) il]->ne[0],
|
||||
ctx_len,
|
||||
lctx.dflash_k_ctx_workspace[(size_t) il]->ne[2],
|
||||
lctx.dflash_k_ctx_workspace[(size_t) il]->nb[1],
|
||||
lctx.dflash_k_ctx_workspace[(size_t) il]->nb[2],
|
||||
0);
|
||||
ggml_tensor * Vdst = ggml_view_3d(ctx0, lctx.dflash_v_ctx_workspace[(size_t) il],
|
||||
lctx.dflash_v_ctx_workspace[(size_t) il]->ne[0],
|
||||
ctx_len,
|
||||
lctx.dflash_v_ctx_workspace[(size_t) il]->ne[2],
|
||||
lctx.dflash_v_ctx_workspace[(size_t) il]->nb[1],
|
||||
lctx.dflash_v_ctx_workspace[(size_t) il]->nb[2],
|
||||
0);
|
||||
|
||||
ggml_tensor * Kstore = ggml_cpy(ctx0, Kworkspace, Kdst);
|
||||
ggml_tensor * Vstore = ggml_cpy(ctx0, Vworkspace, Vdst);
|
||||
cb(Kstore, "dflash_workspace_k_store", il);
|
||||
cb(Vstore, "dflash_workspace_v_store", il);
|
||||
ggml_build_forward_expand(gf, Kstore);
|
||||
ggml_build_forward_expand(gf, Vstore);
|
||||
}
|
||||
|
||||
return gf;
|
||||
}
|
||||
|
||||
ggml_cgraph * llm_build_context::build_dflash_kv_cache() {
|
||||
const int64_t n_embd_head_k = hparams.n_embd_head_k(0);
|
||||
const int64_t n_embd_head_v = hparams.n_embd_head_v(0);
|
||||
|
|
@ -160,6 +273,7 @@ ggml_cgraph * llm_build_context::build_dflash() {
|
|||
const int64_t n_target_features = hparams.dflash_n_target_features;
|
||||
auto & profile = lctx.dflash_profile;
|
||||
const bool use_kv_cache = dflash_use_kv_cache_experiment();
|
||||
const bool use_kv_workspace = use_kv_cache && dflash_use_kv_workspace_experiment();
|
||||
const int64_t ctx_len = lctx.dflash_visible_cross_ctx > 0
|
||||
? (int64_t) lctx.dflash_visible_cross_ctx
|
||||
: std::max<int64_t>(1, (int64_t) cparams.n_ctx - (int64_t) hparams.dflash_block_size);
|
||||
|
|
@ -226,6 +340,7 @@ ggml_cgraph * llm_build_context::build_dflash() {
|
|||
ggml_tensor * inpL = llm_build_inp_embd(ctx0, lctx, hparams, batch, tok_embd, cb);
|
||||
ggml_tensor * inp_pos = build_inp_pos();
|
||||
ggml_tensor * inp_out_ids = (n_tokens > 1 && n_outputs < n_tokens) ? build_inp_out_ids() : nullptr;
|
||||
bool result_rows_selected = false;
|
||||
|
||||
const float kq_scale = 1.0f / std::sqrt((float) n_embd_head_k);
|
||||
|
||||
|
|
@ -258,7 +373,30 @@ ggml_cgraph * llm_build_context::build_dflash() {
|
|||
const int64_t t_cache_read_us = use_kv_cache ? ggml_time_us() : 0;
|
||||
ggml_tensor * Kcur_ctx = nullptr;
|
||||
ggml_tensor * Vcur_ctx = nullptr;
|
||||
if (use_kv_cache) {
|
||||
const bool have_workspace_ctx = use_kv_workspace &&
|
||||
(size_t) il < lctx.dflash_k_ctx_workspace.size() &&
|
||||
(size_t) il < lctx.dflash_v_ctx_workspace.size() &&
|
||||
lctx.dflash_k_ctx_workspace[(size_t) il] != nullptr &&
|
||||
lctx.dflash_v_ctx_workspace[(size_t) il] != nullptr;
|
||||
|
||||
if (have_workspace_ctx) {
|
||||
Kcur_ctx = ggml_view_3d(ctx0, lctx.dflash_k_ctx_workspace[(size_t) il],
|
||||
lctx.dflash_k_ctx_workspace[(size_t) il]->ne[0],
|
||||
ctx_len,
|
||||
lctx.dflash_k_ctx_workspace[(size_t) il]->ne[2],
|
||||
lctx.dflash_k_ctx_workspace[(size_t) il]->nb[1],
|
||||
lctx.dflash_k_ctx_workspace[(size_t) il]->nb[2],
|
||||
0);
|
||||
Vcur_ctx = ggml_view_3d(ctx0, lctx.dflash_v_ctx_workspace[(size_t) il],
|
||||
lctx.dflash_v_ctx_workspace[(size_t) il]->ne[0],
|
||||
ctx_len,
|
||||
lctx.dflash_v_ctx_workspace[(size_t) il]->ne[2],
|
||||
lctx.dflash_v_ctx_workspace[(size_t) il]->nb[1],
|
||||
lctx.dflash_v_ctx_workspace[(size_t) il]->nb[2],
|
||||
0);
|
||||
cb(Kcur_ctx, "Kcur_ctx_workspace", il);
|
||||
cb(Vcur_ctx, "Vcur_ctx_workspace", il);
|
||||
} else if (use_kv_cache) {
|
||||
auto build_ordered_cache_view = [&](ggml_tensor * cache) -> ggml_tensor * {
|
||||
if (!lctx.dflash_kv_cache_view_valid || cache_rows <= 0) {
|
||||
return cache;
|
||||
|
|
@ -267,19 +405,19 @@ ggml_cgraph * llm_build_context::build_dflash() {
|
|||
if (cache_rows < ctx_len) {
|
||||
ggml_tensor * zero_pad = ggml_view_3d(ctx0, cache,
|
||||
cache->ne[0],
|
||||
cache->ne[1],
|
||||
cache->ne[1],
|
||||
ctx_len - cache_rows,
|
||||
cache->nb[1],
|
||||
cache->nb[2],
|
||||
(size_t) cache_rows * cache->nb[2]);
|
||||
(size_t) cache_rows * cache->nb[2]);
|
||||
ggml_tensor * valid = ggml_view_3d(ctx0, cache,
|
||||
cache->ne[0],
|
||||
cache->ne[1],
|
||||
cache->ne[1],
|
||||
cache_rows,
|
||||
cache->nb[1],
|
||||
cache->nb[2],
|
||||
0);
|
||||
return ggml_concat(ctx0, zero_pad, valid, 2);
|
||||
return ggml_concat(ctx0, zero_pad, valid, 2);
|
||||
}
|
||||
|
||||
if (cache_write_pos == 0) {
|
||||
|
|
@ -288,19 +426,19 @@ ggml_cgraph * llm_build_context::build_dflash() {
|
|||
|
||||
ggml_tensor * tail = ggml_view_3d(ctx0, cache,
|
||||
cache->ne[0],
|
||||
cache->ne[1],
|
||||
cache->ne[1],
|
||||
ctx_len - cache_write_pos,
|
||||
cache->nb[1],
|
||||
cache->nb[2],
|
||||
(size_t) cache_write_pos * cache->nb[2]);
|
||||
(size_t) cache_write_pos * cache->nb[2]);
|
||||
ggml_tensor * head = ggml_view_3d(ctx0, cache,
|
||||
cache->ne[0],
|
||||
cache->ne[1],
|
||||
cache->ne[1],
|
||||
cache_write_pos,
|
||||
cache->nb[1],
|
||||
cache->nb[2],
|
||||
0);
|
||||
return ggml_concat(ctx0, tail, head, 2);
|
||||
return ggml_concat(ctx0, tail, head, 2);
|
||||
};
|
||||
|
||||
Kcur_ctx = build_ordered_cache_view(lctx.dflash_k_ctx_cache[(size_t) il]);
|
||||
|
|
@ -321,32 +459,58 @@ ggml_cgraph * llm_build_context::build_dflash() {
|
|||
cb(Vcur_ctx, "Vcur_ctx", il);
|
||||
}
|
||||
|
||||
ggml_tensor * Kcur = ggml_concat(ctx0, Kcur_ctx, Kcur_noise, 2);
|
||||
ggml_tensor * Vcur = ggml_concat(ctx0, Vcur_ctx, Vcur_noise, 2);
|
||||
if (n_kv_pad > 0) {
|
||||
Kcur = ggml_pad(ctx0, Kcur, 0, 0, (int) n_kv_pad, 0);
|
||||
Vcur = ggml_pad(ctx0, Vcur, 0, 0, (int) n_kv_pad, 0);
|
||||
ggml_tensor * Kcur = nullptr;
|
||||
ggml_tensor * Vcur = nullptr;
|
||||
if (have_workspace_ctx) {
|
||||
ggml_tensor * Kcur_draft = ggml_cont(ctx0, ggml_permute(ctx0, Kcur_noise, 0, 2, 1, 3));
|
||||
ggml_tensor * Vcur_draft = ggml_cont(ctx0, ggml_permute(ctx0, Vcur_noise, 0, 2, 1, 3));
|
||||
cb(Kcur_draft, "dflash_main_k_perm_cont", il);
|
||||
cb(Vcur_draft, "dflash_main_v_perm_cont", il);
|
||||
|
||||
Kcur = ggml_concat(ctx0, Kcur_ctx, Kcur_draft, 1);
|
||||
Vcur = ggml_concat(ctx0, Vcur_ctx, Vcur_draft, 1);
|
||||
cb(Kcur, "dflash_main_k_concat", il);
|
||||
cb(Vcur, "dflash_main_v_concat", il);
|
||||
|
||||
if (n_kv_pad > 0) {
|
||||
Kcur = ggml_pad(ctx0, Kcur, 0, (int) n_kv_pad, 0, 0);
|
||||
Vcur = ggml_pad(ctx0, Vcur, 0, (int) n_kv_pad, 0, 0);
|
||||
cb(Kcur, "dflash_main_k_pad", il);
|
||||
cb(Vcur, "dflash_main_v_pad", il);
|
||||
}
|
||||
} else {
|
||||
ggml_tensor * Kcur_concat = ggml_concat(ctx0, Kcur_ctx, Kcur_noise, 2);
|
||||
ggml_tensor * Vcur_concat = ggml_concat(ctx0, Vcur_ctx, Vcur_noise, 2);
|
||||
cb(Kcur_concat, "dflash_main_k_concat", il);
|
||||
cb(Vcur_concat, "dflash_main_v_concat", il);
|
||||
|
||||
Kcur = Kcur_concat;
|
||||
Vcur = Vcur_concat;
|
||||
if (n_kv_pad > 0) {
|
||||
Kcur = ggml_pad(ctx0, Kcur, 0, 0, (int) n_kv_pad, 0);
|
||||
Vcur = ggml_pad(ctx0, Vcur, 0, 0, (int) n_kv_pad, 0);
|
||||
cb(Kcur, "dflash_main_k_pad", il);
|
||||
cb(Vcur, "dflash_main_v_pad", il);
|
||||
}
|
||||
}
|
||||
if (use_kv_cache) {
|
||||
profile.graph_kv_cache_read_concat_pad_us += (uint64_t) (ggml_time_us() - t_cache_read_us);
|
||||
profile.graph_kv_cache_read_concat_pad_calls++;
|
||||
profile.graph_kv_cache_cached_bytes += ggml_nbytes(lctx.dflash_k_ctx_cache[(size_t) il]) + ggml_nbytes(lctx.dflash_v_ctx_cache[(size_t) il]);
|
||||
}
|
||||
cb(Kcur, "Kcur", il);
|
||||
cb(Vcur, "Vcur", il);
|
||||
cb(Qcur, "Qcur", il);
|
||||
cb(Kcur, "Kcur_f16", il);
|
||||
cb(Vcur, "Vcur_f16", il);
|
||||
|
||||
ggml_tensor * q = ggml_permute(ctx0, Qcur, 0, 2, 1, 3);
|
||||
ggml_tensor * k = ggml_cont(ctx0, ggml_permute(ctx0, Kcur, 0, 2, 1, 3));
|
||||
ggml_tensor * v = ggml_cont(ctx0, ggml_permute(ctx0, Vcur, 0, 2, 1, 3));
|
||||
ggml_tensor * k = have_workspace_ctx ? Kcur : ggml_cont(ctx0, ggml_permute(ctx0, Kcur, 0, 2, 1, 3));
|
||||
ggml_tensor * v = have_workspace_ctx ? Vcur : ggml_cont(ctx0, ggml_permute(ctx0, Vcur, 0, 2, 1, 3));
|
||||
ggml_tensor * dflash_kq_mask_l = (hparams.swa_layers[il] && dflash_kq_mask_swa != nullptr)
|
||||
? dflash_kq_mask_swa
|
||||
: dflash_kq_mask_full;
|
||||
cb(q, "q", il);
|
||||
cb(k, "k", il);
|
||||
cb(v, "v", il);
|
||||
if (!have_workspace_ctx) {
|
||||
cb(k, "dflash_main_k_perm_cont", il);
|
||||
cb(v, "dflash_main_v_perm_cont", il);
|
||||
}
|
||||
|
||||
cur = ggml_flash_attn_ext(ctx0, q, k, v, dflash_kq_mask_l, kq_scale, hparams.f_max_alibi_bias,
|
||||
hparams.attn_soft_cap ? hparams.f_attn_logit_softcapping : 0.0f);
|
||||
|
|
@ -362,6 +526,12 @@ ggml_cgraph * llm_build_context::build_dflash() {
|
|||
cur = ggml_add(ctx0, cur, inpSA);
|
||||
cb(cur, "attn_residual", il);
|
||||
|
||||
if (inp_out_ids != nullptr && il == n_layer - 1) {
|
||||
cur = ggml_get_rows(ctx0, cur, inp_out_ids);
|
||||
cb(cur, "result_output_rows", -1);
|
||||
result_rows_selected = true;
|
||||
}
|
||||
|
||||
ggml_tensor * ffn_residual = cur;
|
||||
cur = llm_build_norm(ctx0, cur, hparams, model.layers[il].attn_post_norm, nullptr, LLM_NORM_RMS, cb, il);
|
||||
cb(cur, "attn_post_norm", il);
|
||||
|
|
@ -380,13 +550,13 @@ ggml_cgraph * llm_build_context::build_dflash() {
|
|||
inpL = cur;
|
||||
}
|
||||
|
||||
ggml_tensor * output = model.output;
|
||||
ggml_tensor * output = const_cast<ggml_tensor *>(llama_model_dflash_output_tensor(&model));
|
||||
if (output == nullptr) {
|
||||
output = ggml_new_tensor_2d(ctx0, GGML_TYPE_Q4_0, n_embd, hparams.n_vocab);
|
||||
}
|
||||
|
||||
ggml_tensor * result_input = inpL;
|
||||
if (inp_out_ids) {
|
||||
if (inp_out_ids && !result_rows_selected) {
|
||||
result_input = ggml_get_rows(ctx0, result_input, inp_out_ids);
|
||||
cb(result_input, "result_output_rows", -1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2206,6 +2206,43 @@ struct ggml_cgraph * llm_build_context::llama_build_graph_dflash_kv_cache(llama_
|
|||
return result;
|
||||
}
|
||||
|
||||
struct ggml_cgraph * llm_build_context::llama_build_graph_dflash_kv_workspace(llama_context & lctx) {
|
||||
llama_batch dummy;
|
||||
dummy.n_tokens = 0;
|
||||
|
||||
llm_build_cb cb = [&](struct ggml_tensor * cur, const char * name, int il) {
|
||||
if (il >= 0) {
|
||||
int j = 0;
|
||||
for (; j < GGML_MAX_NAME - 1; ++j) {
|
||||
cur->name[j] = name[j];
|
||||
if (!name[j]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j < GGML_MAX_NAME - 3) {
|
||||
cur->name[j++] = '-';
|
||||
auto sil = std::to_string(il);
|
||||
for (int k = 0; k < (int) sil.size() && j < GGML_MAX_NAME - 1; ++k) {
|
||||
cur->name[j++] = sil[k];
|
||||
}
|
||||
}
|
||||
cur->name[j] = 0;
|
||||
} else {
|
||||
ggml_set_name(cur, name);
|
||||
}
|
||||
};
|
||||
|
||||
struct llm_build_context llm(lctx, dummy, cb, false, false, 0, false, &lctx.dflash_workspace_buf_compute_meta);
|
||||
|
||||
llm.init();
|
||||
|
||||
struct ggml_cgraph * result = llm.build_dflash_kv_workspace();
|
||||
|
||||
llm.free();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ggml_cgraph * llm_build_context::llama_build_graph(
|
||||
llama_context & lctx,
|
||||
const llama_batch & batch,
|
||||
|
|
|
|||
|
|
@ -249,6 +249,8 @@ struct llm_build_context {
|
|||
|
||||
ggml_cgraph * build_dflash_kv_cache();
|
||||
|
||||
ggml_cgraph * build_dflash_kv_workspace();
|
||||
|
||||
ggml_cgraph * build_starcoder2();
|
||||
|
||||
ggml_cgraph * build_mamba();
|
||||
|
|
@ -466,6 +468,8 @@ llm_expert_gating_func_type gating_op,
|
|||
|
||||
static ggml_cgraph * llama_build_graph_dflash_kv_cache(llama_context & lctx);
|
||||
|
||||
static ggml_cgraph * llama_build_graph_dflash_kv_workspace(llama_context & lctx);
|
||||
|
||||
static ggml_cgraph * llama_build_graph(llama_context & lctx, const llama_batch & batch, bool worst_case, int n_outputs = 0);
|
||||
|
||||
ggml_tensor * build_std_attention(ggml_cgraph * gf, ggml_tensor * attn_norm, ggml_tensor * cur,
|
||||
|
|
|
|||
|
|
@ -301,6 +301,8 @@ struct llama_context {
|
|||
int32_t dflash_visible_cross_ctx = 0;
|
||||
std::vector<struct ggml_tensor *> dflash_k_ctx_cache;
|
||||
std::vector<struct ggml_tensor *> dflash_v_ctx_cache;
|
||||
std::vector<struct ggml_tensor *> dflash_k_ctx_workspace;
|
||||
std::vector<struct ggml_tensor *> dflash_v_ctx_workspace;
|
||||
struct ggml_context * dflash_cache_ctx = nullptr;
|
||||
std::vector<ggml_backend_buffer_t> dflash_cache_bufs;
|
||||
int32_t dflash_kv_cache_write_pos = 0;
|
||||
|
|
@ -312,8 +314,24 @@ struct llama_context {
|
|||
uint64_t dflash_kv_cache_applied_window_version = 0;
|
||||
bool dflash_kv_cache_valid = false;
|
||||
bool dflash_kv_cache_view_valid = false;
|
||||
int32_t dflash_kv_workspace_write_pos = 0;
|
||||
int32_t dflash_kv_workspace_n_filled = 0;
|
||||
int32_t dflash_kv_workspace_reserved_rows = 0;
|
||||
int32_t dflash_kv_workspace_token_capacity = 0;
|
||||
int32_t dflash_kv_workspace_n_kv_total = 0;
|
||||
uint64_t dflash_kv_workspace_applied_window_version = 0;
|
||||
bool dflash_kv_workspace_valid = false;
|
||||
bool dflash_kv_workspace_sync_pending = false;
|
||||
std::vector<uint8_t> dflash_buf_compute_meta;
|
||||
std::vector<uint8_t> dflash_workspace_buf_compute_meta;
|
||||
ggml_backend_sched_t dflash_sched = nullptr;
|
||||
ggml_backend_sched_t dflash_workspace_sched = nullptr;
|
||||
ggml_cgraph * dflash_kv_graph = nullptr;
|
||||
ggml_cgraph * dflash_kv_workspace_graph = nullptr;
|
||||
int32_t dflash_kv_graph_rows = 0;
|
||||
int32_t dflash_kv_graph_write_pos = 0;
|
||||
int32_t dflash_kv_workspace_graph_rows = 0;
|
||||
int32_t dflash_kv_workspace_graph_write_pos = 0;
|
||||
struct ggml_tensor * dflash_kv_input_target_features = nullptr;
|
||||
struct ggml_tensor * dflash_kv_input_pos_ctx = nullptr;
|
||||
struct ggml_tensor * dflash_kq_mask_tensor = nullptr;
|
||||
|
|
|
|||
|
|
@ -2202,6 +2202,7 @@ bool create_tensors_helper::create_dflash_tensors(const LLM_TN & tn) {
|
|||
model.tok_embd = create_tensor(ctx_input, tn(LLM_TENSOR_TOKEN_EMBD, "weight"), {n_embd, n_vocab}, llama_model_loader::TENSOR_NOT_REQUIRED);
|
||||
model.output_norm = create_tensor(ctx_output, tn(LLM_TENSOR_OUTPUT_NORM, "weight"), {n_embd}, 0);
|
||||
model.output = create_tensor(ctx_output, tn(LLM_TENSOR_OUTPUT, "weight"), {n_embd, n_vocab}, llama_model_loader::TENSOR_NOT_REQUIRED);
|
||||
model.output_mtp = create_tensor(ctx_output, "output_extra.weight", {n_embd, n_vocab}, llama_model_loader::TENSOR_NOT_REQUIRED);
|
||||
if (model.output == nullptr && model.tok_embd != nullptr) {
|
||||
model.output = create_tensor(ctx_output, tn(LLM_TENSOR_TOKEN_EMBD, "weight"), {n_embd, n_vocab}, llama_model_loader::TENSOR_DUPLICATED);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,11 @@ void llama_reset_dflash_kv_cache_state(struct llama_context * ctx) {
|
|||
ctx->dflash_kv_cache_applied_window_version = 0;
|
||||
ctx->dflash_kv_cache_valid = false;
|
||||
ctx->dflash_kv_cache_view_valid = false;
|
||||
ctx->dflash_kv_workspace_write_pos = 0;
|
||||
ctx->dflash_kv_workspace_n_filled = 0;
|
||||
ctx->dflash_kv_workspace_applied_window_version = 0;
|
||||
ctx->dflash_kv_workspace_valid = false;
|
||||
ctx->dflash_kv_workspace_sync_pending = false;
|
||||
|
||||
for (ggml_backend_buffer_t buf : ctx->dflash_cache_bufs) {
|
||||
if (buf != nullptr) {
|
||||
|
|
@ -171,6 +176,65 @@ int32_t llama_model_dflash_target_mask_token_id(const struct llama_model * model
|
|||
return (int32_t) model->vocab.token_mask();
|
||||
}
|
||||
|
||||
const struct ggml_tensor * llama_model_dflash_output_tensor(
|
||||
const struct llama_model * model) {
|
||||
if (model == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (model->output_mtp != nullptr) {
|
||||
return model->output_mtp;
|
||||
}
|
||||
|
||||
if (model->output != nullptr) {
|
||||
return model->output;
|
||||
}
|
||||
|
||||
return model->tok_embd;
|
||||
}
|
||||
|
||||
static const char * llama_dflash_io_mode_name(int32_t io_mode) {
|
||||
switch (io_mode) {
|
||||
case LLAMA_DFLASH_IO_MODE_SHARED:
|
||||
return "shared";
|
||||
case LLAMA_DFLASH_IO_MODE_SELF_CONTAINED:
|
||||
return "self-contained";
|
||||
case LLAMA_DFLASH_IO_MODE_MIXED:
|
||||
return "mixed";
|
||||
default:
|
||||
return "invalid";
|
||||
}
|
||||
}
|
||||
|
||||
static const char * llama_dflash_output_head_kind(
|
||||
const struct llama_model * draft_model,
|
||||
const struct llama_model * target_model) {
|
||||
const struct ggml_tensor * output = llama_model_dflash_output_tensor(draft_model);
|
||||
if (output == nullptr) {
|
||||
return "missing";
|
||||
}
|
||||
|
||||
if (output == draft_model->tok_embd) {
|
||||
return draft_model->tok_embd == (target_model ? target_model->tok_embd : nullptr)
|
||||
? "shared_token_embedding"
|
||||
: "token_embedding";
|
||||
}
|
||||
|
||||
if (draft_model->output_mtp != nullptr && output == draft_model->output_mtp) {
|
||||
if (target_model != nullptr && target_model->output_mtp != nullptr && output == target_model->output_mtp) {
|
||||
return "output_mtp";
|
||||
}
|
||||
|
||||
if (std::strcmp(output->name, "output_extra.weight") == 0) {
|
||||
return "output_extra";
|
||||
}
|
||||
|
||||
return "output_mtp";
|
||||
}
|
||||
|
||||
return "output";
|
||||
}
|
||||
|
||||
int32_t llama_model_dflash_io_mode(
|
||||
const struct llama_model * draft_model,
|
||||
const struct llama_model * target_model) {
|
||||
|
|
@ -178,13 +242,14 @@ int32_t llama_model_dflash_io_mode(
|
|||
return LLAMA_DFLASH_IO_MODE_INVALID;
|
||||
}
|
||||
|
||||
const ggml_tensor * target_output = target_model->output != nullptr ? target_model->output : target_model->tok_embd;
|
||||
if (draft_model->tok_embd == nullptr || draft_model->output == nullptr || target_model->tok_embd == nullptr || target_output == nullptr) {
|
||||
const ggml_tensor * draft_output = llama_model_dflash_output_tensor(draft_model);
|
||||
const ggml_tensor * target_output = llama_model_dflash_output_tensor(target_model);
|
||||
if (draft_model->tok_embd == nullptr || draft_output == nullptr || target_model->tok_embd == nullptr || target_output == nullptr) {
|
||||
return LLAMA_DFLASH_IO_MODE_INVALID;
|
||||
}
|
||||
|
||||
const bool shared_tok = draft_model->tok_embd == target_model->tok_embd;
|
||||
const bool shared_output = draft_model->output == target_output;
|
||||
const bool shared_output = draft_output == target_output;
|
||||
if (shared_tok && shared_output) {
|
||||
return LLAMA_DFLASH_IO_MODE_SHARED;
|
||||
}
|
||||
|
|
@ -200,14 +265,15 @@ bool llama_model_dflash_io_tensors_match(
|
|||
const struct llama_model * draft_model,
|
||||
int32_t n_embd,
|
||||
int32_t n_vocab) {
|
||||
if (draft_model == nullptr || draft_model->tok_embd == nullptr || draft_model->output == nullptr || n_embd <= 0 || n_vocab <= 0) {
|
||||
const ggml_tensor * output = llama_model_dflash_output_tensor(draft_model);
|
||||
if (draft_model == nullptr || draft_model->tok_embd == nullptr || output == nullptr || n_embd <= 0 || n_vocab <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (int32_t) draft_model->tok_embd->ne[0] == n_embd &&
|
||||
(int32_t) draft_model->tok_embd->ne[1] == n_vocab &&
|
||||
(int32_t) draft_model->output->ne[0] == n_embd &&
|
||||
(int32_t) draft_model->output->ne[1] == n_vocab;
|
||||
(int32_t) output->ne[0] == n_embd &&
|
||||
(int32_t) output->ne[1] == n_vocab;
|
||||
}
|
||||
|
||||
bool llama_model_share_dflash_io_tensors(
|
||||
|
|
@ -232,7 +298,25 @@ bool llama_model_share_dflash_io_tensors(
|
|||
}
|
||||
}
|
||||
|
||||
return draft_model->tok_embd != nullptr && draft_model->output != nullptr;
|
||||
const bool uses_shared_tok = draft_model->tok_embd == target_model->tok_embd;
|
||||
const bool uses_shared_output = draft_model->output == target_model->output ||
|
||||
draft_model->output == target_model->tok_embd;
|
||||
|
||||
if (draft_model->output_mtp == nullptr && target_model->output_mtp != nullptr && uses_shared_tok && uses_shared_output) {
|
||||
draft_model->output_mtp = target_model->output_mtp;
|
||||
}
|
||||
|
||||
const struct ggml_tensor * output = llama_model_dflash_output_tensor(draft_model);
|
||||
if (draft_model->tok_embd != nullptr && output != nullptr) {
|
||||
LLAMA_LOG_INFO("%s: DFlash IO mode=%s output_head=%s tensor=%s type=%s\n",
|
||||
__func__,
|
||||
llama_dflash_io_mode_name(llama_model_dflash_io_mode(draft_model, target_model)),
|
||||
llama_dflash_output_head_kind(draft_model, target_model),
|
||||
output->name[0] != '\0' ? output->name : "(unnamed)",
|
||||
ggml_type_name(output->type));
|
||||
}
|
||||
|
||||
return draft_model->tok_embd != nullptr && output != nullptr;
|
||||
}
|
||||
|
||||
bool llama_set_draft_input_hidden_state_copy(
|
||||
|
|
|
|||
|
|
@ -86,6 +86,13 @@ struct llama_dflash_profile_stats {
|
|||
uint64_t graph_kv_cache_read_concat_pad_calls = 0;
|
||||
uint64_t graph_kv_cache_cached_bytes = 0;
|
||||
uint64_t graph_kv_cache_calls = 0;
|
||||
uint64_t graph_kv_workspace_build_us = 0;
|
||||
uint64_t graph_kv_workspace_reserve_us = 0;
|
||||
uint64_t graph_kv_workspace_reset_us = 0;
|
||||
uint64_t graph_kv_workspace_alloc_us = 0;
|
||||
uint64_t graph_kv_workspace_compute_us = 0;
|
||||
uint64_t graph_kv_workspace_sync_us = 0;
|
||||
uint64_t graph_kv_workspace_calls = 0;
|
||||
uint64_t graph_kv_node_fused_target_calls = 0;
|
||||
uint64_t graph_kv_node_fused_target_us = 0;
|
||||
uint64_t graph_kv_node_k_proj_calls = 0;
|
||||
|
|
@ -100,6 +107,40 @@ struct llama_dflash_profile_stats {
|
|||
uint64_t graph_kv_node_k_store_us = 0;
|
||||
uint64_t graph_kv_node_v_store_calls = 0;
|
||||
uint64_t graph_kv_node_v_store_us = 0;
|
||||
uint64_t graph_main_node_qcur_calls = 0;
|
||||
uint64_t graph_main_node_qcur_us = 0;
|
||||
uint64_t graph_main_node_k_draft_calls = 0;
|
||||
uint64_t graph_main_node_k_draft_us = 0;
|
||||
uint64_t graph_main_node_v_draft_calls = 0;
|
||||
uint64_t graph_main_node_v_draft_us = 0;
|
||||
uint64_t graph_main_node_k_ctx_view_calls = 0;
|
||||
uint64_t graph_main_node_k_ctx_view_us = 0;
|
||||
uint64_t graph_main_node_v_ctx_view_calls = 0;
|
||||
uint64_t graph_main_node_v_ctx_view_us = 0;
|
||||
uint64_t graph_main_node_k_concat_calls = 0;
|
||||
uint64_t graph_main_node_k_concat_us = 0;
|
||||
uint64_t graph_main_node_v_concat_calls = 0;
|
||||
uint64_t graph_main_node_v_concat_us = 0;
|
||||
uint64_t graph_main_node_k_pad_calls = 0;
|
||||
uint64_t graph_main_node_k_pad_us = 0;
|
||||
uint64_t graph_main_node_v_pad_calls = 0;
|
||||
uint64_t graph_main_node_v_pad_us = 0;
|
||||
uint64_t graph_main_node_k_perm_cont_calls = 0;
|
||||
uint64_t graph_main_node_k_perm_cont_us = 0;
|
||||
uint64_t graph_main_node_v_perm_cont_calls = 0;
|
||||
uint64_t graph_main_node_v_perm_cont_us = 0;
|
||||
uint64_t graph_main_node_flash_attn_calls = 0;
|
||||
uint64_t graph_main_node_flash_attn_us = 0;
|
||||
uint64_t graph_main_node_attn_out_calls = 0;
|
||||
uint64_t graph_main_node_attn_out_us = 0;
|
||||
uint64_t graph_main_node_ffn_calls = 0;
|
||||
uint64_t graph_main_node_ffn_us = 0;
|
||||
uint64_t graph_main_node_result_rows_calls = 0;
|
||||
uint64_t graph_main_node_result_rows_us = 0;
|
||||
uint64_t graph_main_node_result_norm_calls = 0;
|
||||
uint64_t graph_main_node_result_norm_us = 0;
|
||||
uint64_t graph_main_node_result_calls = 0;
|
||||
uint64_t graph_main_node_result_us = 0;
|
||||
uint64_t graph_feature_bytes = 0;
|
||||
uint64_t graph_pos_bytes = 0;
|
||||
uint64_t graph_mask_bytes = 0;
|
||||
|
|
@ -232,6 +273,9 @@ int32_t llama_model_dflash_io_mode(
|
|||
const struct llama_model * draft_model,
|
||||
const struct llama_model * target_model);
|
||||
|
||||
const struct ggml_tensor * llama_model_dflash_output_tensor(
|
||||
const struct llama_model * model);
|
||||
|
||||
bool llama_model_dflash_io_tensors_match(
|
||||
const struct llama_model * draft_model,
|
||||
int32_t n_embd,
|
||||
|
|
|
|||
502
src/llama.cpp
502
src/llama.cpp
|
|
@ -190,12 +190,42 @@ enum llama_dflash_kv_node_kind {
|
|||
LLAMA_DFLASH_KV_NODE_V_STORE,
|
||||
};
|
||||
|
||||
enum llama_dflash_main_node_kind {
|
||||
LLAMA_DFLASH_MAIN_NODE_NONE = 0,
|
||||
LLAMA_DFLASH_MAIN_NODE_QCUR,
|
||||
LLAMA_DFLASH_MAIN_NODE_K_DRAFT,
|
||||
LLAMA_DFLASH_MAIN_NODE_V_DRAFT,
|
||||
LLAMA_DFLASH_MAIN_NODE_K_CTX_VIEW,
|
||||
LLAMA_DFLASH_MAIN_NODE_V_CTX_VIEW,
|
||||
LLAMA_DFLASH_MAIN_NODE_K_CONCAT,
|
||||
LLAMA_DFLASH_MAIN_NODE_V_CONCAT,
|
||||
LLAMA_DFLASH_MAIN_NODE_K_PAD,
|
||||
LLAMA_DFLASH_MAIN_NODE_V_PAD,
|
||||
LLAMA_DFLASH_MAIN_NODE_K_PERM_CONT,
|
||||
LLAMA_DFLASH_MAIN_NODE_V_PERM_CONT,
|
||||
LLAMA_DFLASH_MAIN_NODE_FLASH_ATTN,
|
||||
LLAMA_DFLASH_MAIN_NODE_ATTN_OUT,
|
||||
LLAMA_DFLASH_MAIN_NODE_FFN,
|
||||
LLAMA_DFLASH_MAIN_NODE_RESULT_ROWS,
|
||||
LLAMA_DFLASH_MAIN_NODE_RESULT_NORM,
|
||||
LLAMA_DFLASH_MAIN_NODE_RESULT,
|
||||
};
|
||||
|
||||
struct llama_dflash_kv_node_profiler {
|
||||
llama_dflash_profile_stats * profile = nullptr;
|
||||
int64_t t_start_us = 0;
|
||||
llama_dflash_kv_node_kind active_kind = LLAMA_DFLASH_KV_NODE_NONE;
|
||||
};
|
||||
|
||||
struct llama_dflash_main_node_profiler {
|
||||
llama_dflash_profile_stats * profile = nullptr;
|
||||
ggml_backend_sched_eval_callback prev_callback = nullptr;
|
||||
void * prev_user_data = nullptr;
|
||||
bool prev_active = false;
|
||||
int64_t t_start_us = 0;
|
||||
llama_dflash_main_node_kind active_kind = LLAMA_DFLASH_MAIN_NODE_NONE;
|
||||
};
|
||||
|
||||
static bool llama_dflash_tensor_name_has_prefix(const struct ggml_tensor * tensor, const char * prefix) {
|
||||
if (tensor == nullptr || prefix == nullptr || prefix[0] == '\0') {
|
||||
return false;
|
||||
|
|
@ -204,6 +234,16 @@ static bool llama_dflash_tensor_name_has_prefix(const struct ggml_tensor * tenso
|
|||
return std::strncmp(tensor->name, prefix, std::strlen(prefix)) == 0;
|
||||
}
|
||||
|
||||
static bool llama_dflash_tensor_name_matches_label(const struct ggml_tensor * tensor, const char * label) {
|
||||
if (!llama_dflash_tensor_name_has_prefix(tensor, label)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t label_len = std::strlen(label);
|
||||
const char next = tensor->name[label_len];
|
||||
return next == '\0' || next == '-';
|
||||
}
|
||||
|
||||
static llama_dflash_kv_node_kind llama_dflash_kv_node_kind_from_tensor(const struct ggml_tensor * tensor) {
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "dflash_kv_fused_target")) {
|
||||
return LLAMA_DFLASH_KV_NODE_FUSED_TARGET;
|
||||
|
|
@ -268,6 +308,146 @@ static void llama_dflash_kv_node_profile_add(
|
|||
}
|
||||
}
|
||||
|
||||
static llama_dflash_main_node_kind llama_dflash_main_node_kind_from_tensor(const struct ggml_tensor * tensor) {
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "Qcur")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_QCUR;
|
||||
}
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "Kcur_noise")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_K_DRAFT;
|
||||
}
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "Vcur_noise")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_V_DRAFT;
|
||||
}
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "Kcur_ctx_cache")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_K_CTX_VIEW;
|
||||
}
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "Vcur_ctx_cache")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_V_CTX_VIEW;
|
||||
}
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "dflash_main_k_concat")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_K_CONCAT;
|
||||
}
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "dflash_main_v_concat")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_V_CONCAT;
|
||||
}
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "dflash_main_k_pad")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_K_PAD;
|
||||
}
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "dflash_main_v_pad")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_V_PAD;
|
||||
}
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "dflash_main_k_perm_cont")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_K_PERM_CONT;
|
||||
}
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "dflash_main_v_perm_cont")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_V_PERM_CONT;
|
||||
}
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "flash_attn_reshaped")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_NONE;
|
||||
}
|
||||
if (llama_dflash_tensor_name_matches_label(tensor, "flash_attn")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_FLASH_ATTN;
|
||||
}
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "kqv_out")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_ATTN_OUT;
|
||||
}
|
||||
if (llama_dflash_tensor_name_has_prefix(tensor, "ffn_out")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_FFN;
|
||||
}
|
||||
if (llama_dflash_tensor_name_matches_label(tensor, "result_output_rows")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_RESULT_ROWS;
|
||||
}
|
||||
if (llama_dflash_tensor_name_matches_label(tensor, "result_norm")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_RESULT_NORM;
|
||||
}
|
||||
if (llama_dflash_tensor_name_matches_label(tensor, "output")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_RESULT;
|
||||
}
|
||||
if (llama_dflash_tensor_name_matches_label(tensor, "result_output")) {
|
||||
return LLAMA_DFLASH_MAIN_NODE_RESULT;
|
||||
}
|
||||
|
||||
return LLAMA_DFLASH_MAIN_NODE_NONE;
|
||||
}
|
||||
|
||||
static void llama_dflash_main_node_profile_add(
|
||||
llama_dflash_profile_stats & profile,
|
||||
llama_dflash_main_node_kind kind,
|
||||
uint64_t elapsed_us) {
|
||||
switch (kind) {
|
||||
case LLAMA_DFLASH_MAIN_NODE_QCUR:
|
||||
profile.graph_main_node_qcur_calls++;
|
||||
profile.graph_main_node_qcur_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_K_DRAFT:
|
||||
profile.graph_main_node_k_draft_calls++;
|
||||
profile.graph_main_node_k_draft_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_V_DRAFT:
|
||||
profile.graph_main_node_v_draft_calls++;
|
||||
profile.graph_main_node_v_draft_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_K_CTX_VIEW:
|
||||
profile.graph_main_node_k_ctx_view_calls++;
|
||||
profile.graph_main_node_k_ctx_view_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_V_CTX_VIEW:
|
||||
profile.graph_main_node_v_ctx_view_calls++;
|
||||
profile.graph_main_node_v_ctx_view_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_K_CONCAT:
|
||||
profile.graph_main_node_k_concat_calls++;
|
||||
profile.graph_main_node_k_concat_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_V_CONCAT:
|
||||
profile.graph_main_node_v_concat_calls++;
|
||||
profile.graph_main_node_v_concat_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_K_PAD:
|
||||
profile.graph_main_node_k_pad_calls++;
|
||||
profile.graph_main_node_k_pad_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_V_PAD:
|
||||
profile.graph_main_node_v_pad_calls++;
|
||||
profile.graph_main_node_v_pad_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_K_PERM_CONT:
|
||||
profile.graph_main_node_k_perm_cont_calls++;
|
||||
profile.graph_main_node_k_perm_cont_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_V_PERM_CONT:
|
||||
profile.graph_main_node_v_perm_cont_calls++;
|
||||
profile.graph_main_node_v_perm_cont_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_FLASH_ATTN:
|
||||
profile.graph_main_node_flash_attn_calls++;
|
||||
profile.graph_main_node_flash_attn_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_ATTN_OUT:
|
||||
profile.graph_main_node_attn_out_calls++;
|
||||
profile.graph_main_node_attn_out_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_FFN:
|
||||
profile.graph_main_node_ffn_calls++;
|
||||
profile.graph_main_node_ffn_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_RESULT_ROWS:
|
||||
profile.graph_main_node_result_rows_calls++;
|
||||
profile.graph_main_node_result_rows_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_RESULT_NORM:
|
||||
profile.graph_main_node_result_norm_calls++;
|
||||
profile.graph_main_node_result_norm_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_RESULT:
|
||||
profile.graph_main_node_result_calls++;
|
||||
profile.graph_main_node_result_us += elapsed_us;
|
||||
break;
|
||||
case LLAMA_DFLASH_MAIN_NODE_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool llama_dflash_kv_node_eval_callback(struct ggml_tensor * tensor, bool ask, void * user_data) {
|
||||
auto * profiler = static_cast<llama_dflash_kv_node_profiler *>(user_data);
|
||||
if (profiler == nullptr || profiler->profile == nullptr) {
|
||||
|
|
@ -294,6 +474,62 @@ static bool llama_dflash_kv_node_eval_callback(struct ggml_tensor * tensor, bool
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool llama_dflash_main_node_eval_callback(struct ggml_tensor * tensor, bool ask, void * user_data) {
|
||||
auto * profiler = static_cast<llama_dflash_main_node_profiler *>(user_data);
|
||||
if (profiler == nullptr || profiler->profile == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const llama_dflash_main_node_kind kind = llama_dflash_main_node_kind_from_tensor(tensor);
|
||||
if (ask) {
|
||||
profiler->prev_active = profiler->prev_callback != nullptr
|
||||
? profiler->prev_callback(tensor, ask, profiler->prev_user_data)
|
||||
: false;
|
||||
|
||||
if (kind == LLAMA_DFLASH_MAIN_NODE_NONE) {
|
||||
profiler->active_kind = LLAMA_DFLASH_MAIN_NODE_NONE;
|
||||
profiler->t_start_us = 0;
|
||||
return profiler->prev_active;
|
||||
}
|
||||
|
||||
profiler->active_kind = kind;
|
||||
profiler->t_start_us = ggml_time_us();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool prev_result = false;
|
||||
if (profiler->prev_active && profiler->prev_callback != nullptr) {
|
||||
prev_result = profiler->prev_callback(tensor, ask, profiler->prev_user_data);
|
||||
}
|
||||
|
||||
const bool tracked = kind != LLAMA_DFLASH_MAIN_NODE_NONE &&
|
||||
profiler->active_kind == kind &&
|
||||
profiler->t_start_us > 0;
|
||||
if (tracked) {
|
||||
llama_dflash_main_node_profile_add(*profiler->profile, kind, (uint64_t) (ggml_time_us() - profiler->t_start_us));
|
||||
}
|
||||
|
||||
profiler->prev_active = false;
|
||||
profiler->active_kind = LLAMA_DFLASH_MAIN_NODE_NONE;
|
||||
profiler->t_start_us = 0;
|
||||
return prev_result || tracked;
|
||||
}
|
||||
|
||||
static bool llama_dflash_use_kv_workspace_experiment() {
|
||||
return llama_env_flag_enabled("IK_DFLASH_KV_WORKSPACE");
|
||||
}
|
||||
|
||||
static void llama_sync_dflash_workspace_if_pending(struct llama_context & lctx) {
|
||||
if (!lctx.dflash_kv_workspace_sync_pending || lctx.dflash_workspace_sched == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int64_t t_workspace_sync_us = ggml_time_us();
|
||||
ggml_backend_sched_synchronize(lctx.dflash_workspace_sched);
|
||||
lctx.dflash_profile.graph_kv_workspace_sync_us += (uint64_t) (ggml_time_us() - t_workspace_sync_us);
|
||||
lctx.dflash_kv_workspace_sync_pending = false;
|
||||
}
|
||||
|
||||
// extract ip and port from RPC[ip:port] for rpc and keep other device names
|
||||
static std::vector<rpc_device> extract_device_from_rpc_device(std::vector<std::string> devices) {
|
||||
std::vector<rpc_device> rpc_servers;
|
||||
|
|
@ -727,16 +963,26 @@ static ggml_backend_t llama_backend_for_tensor(const llama_context & lctx, const
|
|||
}
|
||||
|
||||
bool llama_context::ensure_dflash_kv_cache_tensors(int32_t cross_ctx) {
|
||||
const bool use_kv_workspace = llama_env_flag_enabled("IK_DFLASH_KV_WORKSPACE");
|
||||
const int32_t target_cross_ctx = std::max<int32_t>(1, cross_ctx);
|
||||
const int32_t target_token_capacity = std::max<int32_t>(1, (int32_t) model.hparams.dflash_block_size);
|
||||
const int32_t target_workspace_n_kv_total = GGML_PAD(target_cross_ctx + target_token_capacity, cparams.flash_attn ? 256 : 32);
|
||||
const int32_t n_layer = model.hparams.n_layer;
|
||||
const int64_t n_embd_head_k = model.hparams.n_embd_head_k(0);
|
||||
const int64_t n_embd_head_v = model.hparams.n_embd_head_v(0);
|
||||
const int64_t n_head_kv = model.hparams.n_head_kv();
|
||||
|
||||
if (dflash_cache_ctx != nullptr && !dflash_k_ctx_cache.empty()) {
|
||||
if ((int32_t) dflash_k_ctx_cache.size() == n_layer &&
|
||||
dflash_k_ctx_cache.front() != nullptr &&
|
||||
(int32_t) dflash_k_ctx_cache.front()->ne[2] == target_cross_ctx) {
|
||||
const bool cache_matches = (int32_t) dflash_k_ctx_cache.size() == n_layer &&
|
||||
dflash_k_ctx_cache.front() != nullptr &&
|
||||
(int32_t) dflash_k_ctx_cache.front()->ne[2] == target_cross_ctx;
|
||||
const bool workspace_matches = use_kv_workspace
|
||||
? ((int32_t) dflash_k_ctx_workspace.size() == n_layer &&
|
||||
dflash_k_ctx_workspace.front() != nullptr &&
|
||||
(int32_t) dflash_k_ctx_workspace.front()->ne[1] == target_workspace_n_kv_total)
|
||||
: dflash_k_ctx_workspace.empty() && dflash_v_ctx_workspace.empty();
|
||||
|
||||
if (cache_matches && workspace_matches) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -745,11 +991,23 @@ bool llama_context::ensure_dflash_kv_cache_tensors(int32_t cross_ctx) {
|
|||
ggml_backend_sched_free(dflash_sched);
|
||||
dflash_sched = nullptr;
|
||||
}
|
||||
if (dflash_workspace_sched != nullptr) {
|
||||
ggml_backend_sched_free(dflash_workspace_sched);
|
||||
dflash_workspace_sched = nullptr;
|
||||
}
|
||||
dflash_kv_graph = nullptr;
|
||||
dflash_kv_workspace_graph = nullptr;
|
||||
dflash_kv_graph_rows = 0;
|
||||
dflash_kv_graph_write_pos = 0;
|
||||
dflash_kv_workspace_graph_rows = 0;
|
||||
dflash_kv_workspace_graph_write_pos = 0;
|
||||
dflash_kv_workspace_reserved_rows = 0;
|
||||
dflash_buf_compute_meta.clear();
|
||||
dflash_workspace_buf_compute_meta.clear();
|
||||
}
|
||||
|
||||
ggml_init_params params = {
|
||||
/*.mem_size =*/ (size_t) (2 * std::max(1, n_layer)) * ggml_tensor_overhead(),
|
||||
/*.mem_size =*/ (size_t) ((use_kv_workspace ? 4 : 2) * std::max(1, n_layer)) * ggml_tensor_overhead(),
|
||||
/*.mem_buffer =*/ nullptr,
|
||||
/*.no_alloc =*/ true,
|
||||
};
|
||||
|
|
@ -761,8 +1019,14 @@ bool llama_context::ensure_dflash_kv_cache_tensors(int32_t cross_ctx) {
|
|||
|
||||
dflash_k_ctx_cache.resize((size_t) n_layer);
|
||||
dflash_v_ctx_cache.resize((size_t) n_layer);
|
||||
dflash_k_ctx_workspace.clear();
|
||||
dflash_v_ctx_workspace.clear();
|
||||
if (use_kv_workspace) {
|
||||
dflash_k_ctx_workspace.resize((size_t) n_layer);
|
||||
dflash_v_ctx_workspace.resize((size_t) n_layer);
|
||||
}
|
||||
dflash_cache_bufs.clear();
|
||||
dflash_cache_bufs.reserve((size_t) std::max(1, n_layer) * 2);
|
||||
dflash_cache_bufs.reserve((size_t) std::max(1, n_layer) * (use_kv_workspace ? 4 : 2));
|
||||
int32_t host_layers = 0;
|
||||
const char * first_buft_name = nullptr;
|
||||
const char * last_buft_name = nullptr;
|
||||
|
|
@ -809,9 +1073,47 @@ bool llama_context::ensure_dflash_kv_cache_tensors(int32_t cross_ctx) {
|
|||
ggml_backend_tensor_alloc(v_buf, dflash_v_ctx_cache[(size_t) il], ggml_backend_buffer_get_base(v_buf));
|
||||
ggml_backend_buffer_clear(v_buf, 0);
|
||||
dflash_cache_bufs.push_back(v_buf);
|
||||
|
||||
if (use_kv_workspace) {
|
||||
dflash_k_ctx_workspace[(size_t) il] = ggml_new_tensor_3d(dflash_cache_ctx, GGML_TYPE_F32, n_embd_head_k, target_workspace_n_kv_total, n_head_kv);
|
||||
dflash_v_ctx_workspace[(size_t) il] = ggml_new_tensor_3d(dflash_cache_ctx, GGML_TYPE_F32, n_embd_head_v, target_workspace_n_kv_total, n_head_kv);
|
||||
if (dflash_k_ctx_workspace[(size_t) il] == nullptr || dflash_v_ctx_workspace[(size_t) il] == nullptr) {
|
||||
free_dflash_kv_cache_tensors();
|
||||
return false;
|
||||
}
|
||||
|
||||
ggml_set_input(dflash_k_ctx_workspace[(size_t) il]);
|
||||
ggml_set_input(dflash_v_ctx_workspace[(size_t) il]);
|
||||
ggml_format_name(dflash_k_ctx_workspace[(size_t) il], "dflash_k_ctx_workspace_%d", il);
|
||||
ggml_format_name(dflash_v_ctx_workspace[(size_t) il], "dflash_v_ctx_workspace_%d", il);
|
||||
|
||||
const size_t k_workspace_bytes = ggml_backend_buft_get_alloc_size(layer_buft, dflash_k_ctx_workspace[(size_t) il]);
|
||||
ggml_backend_buffer_t k_workspace_buf = ggml_backend_buft_alloc_buffer(layer_buft, k_workspace_bytes);
|
||||
if (k_workspace_buf == nullptr) {
|
||||
free_dflash_kv_cache_tensors();
|
||||
return false;
|
||||
}
|
||||
ggml_backend_buffer_set_usage(k_workspace_buf, GGML_BACKEND_BUFFER_USAGE_COMPUTE);
|
||||
ggml_backend_tensor_alloc(k_workspace_buf, dflash_k_ctx_workspace[(size_t) il], ggml_backend_buffer_get_base(k_workspace_buf));
|
||||
ggml_backend_buffer_clear(k_workspace_buf, 0);
|
||||
dflash_cache_bufs.push_back(k_workspace_buf);
|
||||
|
||||
const size_t v_workspace_bytes = ggml_backend_buft_get_alloc_size(layer_buft, dflash_v_ctx_workspace[(size_t) il]);
|
||||
ggml_backend_buffer_t v_workspace_buf = ggml_backend_buft_alloc_buffer(layer_buft, v_workspace_bytes);
|
||||
if (v_workspace_buf == nullptr) {
|
||||
free_dflash_kv_cache_tensors();
|
||||
return false;
|
||||
}
|
||||
ggml_backend_buffer_set_usage(v_workspace_buf, GGML_BACKEND_BUFFER_USAGE_COMPUTE);
|
||||
ggml_backend_tensor_alloc(v_workspace_buf, dflash_v_ctx_workspace[(size_t) il], ggml_backend_buffer_get_base(v_workspace_buf));
|
||||
ggml_backend_buffer_clear(v_workspace_buf, 0);
|
||||
dflash_cache_bufs.push_back(v_workspace_buf);
|
||||
}
|
||||
}
|
||||
|
||||
dflash_profile.last_kv_cache_host_layers = host_layers;
|
||||
dflash_kv_workspace_token_capacity = use_kv_workspace ? target_token_capacity : 0;
|
||||
dflash_kv_workspace_n_kv_total = use_kv_workspace ? target_workspace_n_kv_total : 0;
|
||||
llama_reset_dflash_kv_cache_state(this);
|
||||
LLAMA_LOG_INFO("%s: DFlash K/V cache placement cross_ctx=%d host_layers=%d/%d first=%s last=%s\n",
|
||||
__func__,
|
||||
|
|
@ -827,6 +1129,8 @@ bool llama_context::ensure_dflash_kv_cache_tensors(int32_t cross_ctx) {
|
|||
void llama_context::free_dflash_kv_cache_tensors() {
|
||||
dflash_k_ctx_cache.clear();
|
||||
dflash_v_ctx_cache.clear();
|
||||
dflash_k_ctx_workspace.clear();
|
||||
dflash_v_ctx_workspace.clear();
|
||||
dflash_kv_cache_write_pos = 0;
|
||||
dflash_kv_cache_n_filled = 0;
|
||||
dflash_kv_cache_update_rows = 0;
|
||||
|
|
@ -836,11 +1140,31 @@ void llama_context::free_dflash_kv_cache_tensors() {
|
|||
dflash_kv_cache_applied_window_version = 0;
|
||||
dflash_kv_cache_valid = false;
|
||||
dflash_kv_cache_view_valid = false;
|
||||
dflash_kv_workspace_write_pos = 0;
|
||||
dflash_kv_workspace_n_filled = 0;
|
||||
dflash_kv_workspace_reserved_rows = 0;
|
||||
dflash_kv_workspace_token_capacity = 0;
|
||||
dflash_kv_workspace_n_kv_total = 0;
|
||||
dflash_kv_workspace_applied_window_version = 0;
|
||||
dflash_kv_workspace_valid = false;
|
||||
dflash_kv_workspace_sync_pending = false;
|
||||
dflash_kv_graph = nullptr;
|
||||
dflash_kv_workspace_graph = nullptr;
|
||||
dflash_kv_graph_rows = 0;
|
||||
dflash_kv_graph_write_pos = 0;
|
||||
dflash_kv_workspace_graph_rows = 0;
|
||||
dflash_kv_workspace_graph_write_pos = 0;
|
||||
dflash_kv_input_target_features = nullptr;
|
||||
dflash_kv_input_pos_ctx = nullptr;
|
||||
dflash_kq_mask_tensor = nullptr;
|
||||
dflash_kq_mask_swa_tensor = nullptr;
|
||||
|
||||
if (dflash_workspace_sched != nullptr) {
|
||||
ggml_backend_sched_synchronize(dflash_workspace_sched);
|
||||
ggml_backend_sched_free(dflash_workspace_sched);
|
||||
dflash_workspace_sched = nullptr;
|
||||
}
|
||||
|
||||
for (ggml_backend_buffer_t buf : dflash_cache_bufs) {
|
||||
if (buf != nullptr) {
|
||||
ggml_backend_buffer_free(buf);
|
||||
|
|
@ -4229,7 +4553,7 @@ static bool llm_load_tensors(
|
|||
if (model.arch == LLM_ARCH_GEMMA4) {
|
||||
llm_scale_gate_inp_s(model, use_mmap_buffer);
|
||||
}
|
||||
if ((model.arch == LLM_ARCH_QWEN35 || model.arch == LLM_ARCH_QWEN35MOE) && extra_output_type != GGML_TYPE_COUNT) {
|
||||
if ((model.arch == LLM_ARCH_QWEN35 || model.arch == LLM_ARCH_QWEN35MOE || model.arch == LLM_ARCH_DFLASH_DRAFT) && extra_output_type != GGML_TYPE_COUNT) {
|
||||
llm_requantize_output_tensor(model, extra_output_type);
|
||||
}
|
||||
|
||||
|
|
@ -5405,6 +5729,7 @@ static bool prepare_dflash_graph_inputs(
|
|||
struct llama_context & lctx,
|
||||
uint32_t n_tokens) {
|
||||
const bool use_kv_cache = llama_env_flag_enabled("IK_DFLASH_KV_CACHE");
|
||||
const bool use_kv_workspace = use_kv_cache && llama_dflash_use_kv_workspace_experiment();
|
||||
const bool kv_node_timing = llama_env_flag_enabled("IK_DFLASH_KV_NODE_TIMING");
|
||||
auto & profile = lctx.dflash_profile;
|
||||
const int32_t cross_ctx = lctx.dflash_visible_cross_ctx > 0
|
||||
|
|
@ -5456,6 +5781,10 @@ static bool prepare_dflash_graph_inputs(
|
|||
profile.last_n_tokens = (int32_t) n_tokens;
|
||||
profile.last_n_kv_total = n_kv_total;
|
||||
|
||||
if (use_kv_workspace) {
|
||||
llama_sync_dflash_workspace_if_pending(lctx);
|
||||
}
|
||||
|
||||
if (graph_cross_ctx != cross_ctx) {
|
||||
profile.graph_shape_failures++;
|
||||
|
||||
|
|
@ -5585,6 +5914,9 @@ static bool prepare_dflash_graph_inputs(
|
|||
ggml_backend_sched_free(lctx.dflash_sched);
|
||||
lctx.dflash_sched = nullptr;
|
||||
}
|
||||
lctx.dflash_kv_graph = nullptr;
|
||||
lctx.dflash_kv_graph_rows = 0;
|
||||
lctx.dflash_kv_graph_write_pos = 0;
|
||||
|
||||
const int32_t saved_update_rows = lctx.dflash_kv_cache_update_rows;
|
||||
lctx.dflash_kv_cache_update_rows = cross_ctx;
|
||||
|
|
@ -5631,23 +5963,35 @@ static bool prepare_dflash_graph_inputs(
|
|||
}
|
||||
|
||||
lctx.dflash_kv_cache_update_rows = update_rows;
|
||||
const int64_t t_build_us = ggml_time_us();
|
||||
ggml_cgraph * gf_kv = llm_build_context::llama_build_graph_dflash_kv_cache(lctx);
|
||||
profile.graph_kv_cache_build_us += (uint64_t) (ggml_time_us() - t_build_us);
|
||||
if (gf_kv == nullptr || lctx.dflash_kv_input_target_features == nullptr || lctx.dflash_kv_input_pos_ctx == nullptr) {
|
||||
profile.graph_shape_failures++;
|
||||
LLAMA_LOG_ERROR("%s: failed to build DFlash K/V cache graph\n", __func__);
|
||||
return false;
|
||||
ggml_cgraph * gf_kv = nullptr;
|
||||
const bool can_reuse_kv_graph = lctx.dflash_kv_graph != nullptr &&
|
||||
lctx.dflash_kv_graph_rows == update_rows &&
|
||||
lctx.dflash_kv_graph_write_pos == lctx.dflash_kv_cache_write_pos;
|
||||
if (can_reuse_kv_graph) {
|
||||
gf_kv = lctx.dflash_kv_graph;
|
||||
} else {
|
||||
const int64_t t_build_us = ggml_time_us();
|
||||
gf_kv = llm_build_context::llama_build_graph_dflash_kv_cache(lctx);
|
||||
profile.graph_kv_cache_build_us += (uint64_t) (ggml_time_us() - t_build_us);
|
||||
if (gf_kv == nullptr || lctx.dflash_kv_input_target_features == nullptr || lctx.dflash_kv_input_pos_ctx == nullptr) {
|
||||
profile.graph_shape_failures++;
|
||||
LLAMA_LOG_ERROR("%s: failed to build DFlash K/V cache graph\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
const int64_t t_reset_us = ggml_time_us();
|
||||
ggml_backend_sched_reset(lctx.dflash_sched);
|
||||
profile.graph_kv_cache_reset_us += (uint64_t) (ggml_time_us() - t_reset_us);
|
||||
|
||||
const int64_t t_alloc_us = ggml_time_us();
|
||||
ggml_backend_sched_alloc_graph(lctx.dflash_sched, gf_kv);
|
||||
profile.graph_kv_cache_alloc_us += (uint64_t) (ggml_time_us() - t_alloc_us);
|
||||
|
||||
lctx.dflash_kv_graph = gf_kv;
|
||||
lctx.dflash_kv_graph_rows = update_rows;
|
||||
lctx.dflash_kv_graph_write_pos = lctx.dflash_kv_cache_write_pos;
|
||||
}
|
||||
|
||||
const int64_t t_reset_us = ggml_time_us();
|
||||
ggml_backend_sched_reset(lctx.dflash_sched);
|
||||
profile.graph_kv_cache_reset_us += (uint64_t) (ggml_time_us() - t_reset_us);
|
||||
|
||||
const int64_t t_alloc_us = ggml_time_us();
|
||||
ggml_backend_sched_alloc_graph(lctx.dflash_sched, gf_kv);
|
||||
profile.graph_kv_cache_alloc_us += (uint64_t) (ggml_time_us() - t_alloc_us);
|
||||
|
||||
ggml_backend_t kv_feature_backend = llama_backend_for_tensor(lctx, lctx.dflash_kv_input_target_features);
|
||||
const int64_t t_feature_upload_us = ggml_time_us();
|
||||
if (kv_feature_backend != nullptr) {
|
||||
|
|
@ -5692,6 +6036,108 @@ static bool prepare_dflash_graph_inputs(
|
|||
lctx.dflash_kv_cache_view_write_pos = lctx.dflash_kv_cache_write_pos;
|
||||
lctx.dflash_kv_cache_view_valid = true;
|
||||
}
|
||||
|
||||
if (use_kv_workspace && lctx.dflash_kv_cache_view_valid &&
|
||||
!lctx.dflash_k_ctx_workspace.empty() && !lctx.dflash_v_ctx_workspace.empty()) {
|
||||
const bool need_workspace_refresh = !lctx.dflash_kv_workspace_valid ||
|
||||
lctx.dflash_kv_workspace_n_filled != lctx.dflash_kv_cache_view_n_filled ||
|
||||
lctx.dflash_kv_workspace_write_pos != lctx.dflash_kv_cache_view_write_pos ||
|
||||
lctx.dflash_kv_workspace_applied_window_version != lctx.dflash_kv_cache_applied_window_version;
|
||||
|
||||
if (need_workspace_refresh) {
|
||||
const size_t max_nodes = lctx.model.max_nodes((int) std::max<int32_t>(1, cross_ctx)) + 16 * lctx.model.hparams.n_layer;
|
||||
const size_t meta_size = ggml_tensor_overhead()*max_nodes + ggml_graph_overhead_custom(max_nodes, false);
|
||||
if (lctx.dflash_workspace_buf_compute_meta.size() != meta_size) {
|
||||
lctx.dflash_workspace_buf_compute_meta.resize(meta_size);
|
||||
}
|
||||
|
||||
ggml_cgraph * gf_workspace = nullptr;
|
||||
const bool can_reuse_workspace_graph = lctx.dflash_kv_workspace_graph != nullptr &&
|
||||
lctx.dflash_kv_workspace_graph_rows == lctx.dflash_kv_cache_view_n_filled &&
|
||||
lctx.dflash_kv_workspace_graph_write_pos == lctx.dflash_kv_cache_view_write_pos;
|
||||
|
||||
if (can_reuse_workspace_graph) {
|
||||
gf_workspace = lctx.dflash_kv_workspace_graph;
|
||||
} else {
|
||||
const int64_t t_build_us = ggml_time_us();
|
||||
gf_workspace = llm_build_context::llama_build_graph_dflash_kv_workspace(lctx);
|
||||
profile.graph_kv_workspace_build_us += (uint64_t) (ggml_time_us() - t_build_us);
|
||||
if (gf_workspace == nullptr) {
|
||||
profile.graph_shape_failures++;
|
||||
LLAMA_LOG_ERROR("%s: failed to build DFlash K/V workspace graph\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<ggml_backend_buffer_type_t> backend_buft;
|
||||
backend_buft.reserve(lctx.backends.size());
|
||||
for (auto * backend : lctx.backends) {
|
||||
if (ggml_backend_is_cpu(backend)) {
|
||||
backend_buft.push_back(llama_default_buffer_type_cpu(true));
|
||||
} else {
|
||||
backend_buft.push_back(ggml_backend_get_default_buffer_type(backend));
|
||||
}
|
||||
}
|
||||
|
||||
if (lctx.dflash_workspace_sched == nullptr) {
|
||||
lctx.dflash_workspace_sched = ggml_backend_sched_new(lctx.backends.data(), backend_buft.data(), lctx.backends.size(), max_nodes, false);
|
||||
}
|
||||
|
||||
if (lctx.dflash_kv_workspace_reserved_rows != cross_ctx) {
|
||||
const bool saved_view_valid = lctx.dflash_kv_cache_view_valid;
|
||||
const int32_t saved_view_rows = lctx.dflash_kv_cache_view_n_filled;
|
||||
const int32_t saved_view_write_pos = lctx.dflash_kv_cache_view_write_pos;
|
||||
|
||||
lctx.dflash_kv_cache_view_valid = true;
|
||||
lctx.dflash_kv_cache_view_n_filled = cross_ctx;
|
||||
lctx.dflash_kv_cache_view_write_pos = cross_ctx > 1 ? 1 : 0;
|
||||
|
||||
const int64_t t_reserve_build_us = ggml_time_us();
|
||||
ggml_cgraph * gf_workspace_reserve = llm_build_context::llama_build_graph_dflash_kv_workspace(lctx);
|
||||
profile.graph_kv_workspace_build_us += (uint64_t) (ggml_time_us() - t_reserve_build_us);
|
||||
|
||||
lctx.dflash_kv_cache_view_valid = saved_view_valid;
|
||||
lctx.dflash_kv_cache_view_n_filled = saved_view_rows;
|
||||
lctx.dflash_kv_cache_view_write_pos = saved_view_write_pos;
|
||||
|
||||
const int64_t t_reserve_us = ggml_time_us();
|
||||
const bool reserved = lctx.dflash_workspace_sched != nullptr &&
|
||||
gf_workspace_reserve != nullptr &&
|
||||
ggml_backend_sched_reserve(lctx.dflash_workspace_sched, gf_workspace_reserve);
|
||||
profile.graph_kv_workspace_reserve_us += (uint64_t) (ggml_time_us() - t_reserve_us);
|
||||
if (!reserved) {
|
||||
profile.graph_shape_failures++;
|
||||
LLAMA_LOG_ERROR("%s: failed to initialize DFlash K/V workspace scheduler\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
lctx.dflash_kv_workspace_reserved_rows = cross_ctx;
|
||||
}
|
||||
|
||||
const int64_t t_reset_us = ggml_time_us();
|
||||
ggml_backend_sched_reset(lctx.dflash_workspace_sched);
|
||||
profile.graph_kv_workspace_reset_us += (uint64_t) (ggml_time_us() - t_reset_us);
|
||||
|
||||
const int64_t t_alloc_us = ggml_time_us();
|
||||
ggml_backend_sched_alloc_graph(lctx.dflash_workspace_sched, gf_workspace);
|
||||
profile.graph_kv_workspace_alloc_us += (uint64_t) (ggml_time_us() - t_alloc_us);
|
||||
|
||||
lctx.dflash_kv_workspace_graph = gf_workspace;
|
||||
lctx.dflash_kv_workspace_graph_rows = lctx.dflash_kv_cache_view_n_filled;
|
||||
lctx.dflash_kv_workspace_graph_write_pos = lctx.dflash_kv_cache_view_write_pos;
|
||||
}
|
||||
|
||||
const int64_t t_workspace_us = ggml_time_us();
|
||||
llama_graph_compute_sched(lctx, lctx.dflash_workspace_sched, gf_workspace, lctx.cparams.n_threads);
|
||||
profile.graph_kv_workspace_compute_us += (uint64_t) (ggml_time_us() - t_workspace_us);
|
||||
lctx.dflash_kv_workspace_sync_pending = true;
|
||||
profile.graph_kv_workspace_calls++;
|
||||
|
||||
lctx.dflash_kv_workspace_n_filled = lctx.dflash_kv_cache_view_n_filled;
|
||||
lctx.dflash_kv_workspace_write_pos = lctx.dflash_kv_cache_view_write_pos;
|
||||
lctx.dflash_kv_workspace_applied_window_version = lctx.dflash_kv_cache_applied_window_version;
|
||||
lctx.dflash_kv_workspace_valid = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ggml_backend_tensor_set(lctx.inp_dflash_target_features, lctx.dflash_target_features_padded.data(), 0, ggml_nbytes(lctx.inp_dflash_target_features));
|
||||
ggml_backend_tensor_set(lctx.inp_dflash_pos_ctx, lctx.dflash_pos_ctx_data.data(), 0, ggml_nbytes(lctx.inp_dflash_pos_ctx));
|
||||
|
|
@ -5806,6 +6252,7 @@ static int llama_decode_internal(
|
|||
|
||||
auto * dflash_profile = lctx.model.arch == LLM_ARCH_DFLASH_DRAFT ? &lctx.dflash_profile : nullptr;
|
||||
const bool dflash_decode_timing = dflash_profile != nullptr && llama_env_flag_enabled("IK_DFLASH_DECODE_TIMING");
|
||||
const bool dflash_draft_node_timing = dflash_profile != nullptr && llama_env_flag_enabled("IK_DFLASH_DRAFT_NODE_TIMING");
|
||||
|
||||
auto & kv_self = lctx.kv_self;
|
||||
|
||||
|
|
@ -6165,8 +6612,21 @@ static int llama_decode_internal(
|
|||
#if IK_PRINT_TIMING
|
||||
tim1 = ggml_time_us();
|
||||
#endif
|
||||
if (lctx.dflash_kv_workspace_sync_pending) {
|
||||
llama_sync_dflash_workspace_if_pending(lctx);
|
||||
}
|
||||
const int64_t t_dflash_graph_compute_us = dflash_decode_timing ? ggml_time_us() : 0;
|
||||
llama_dflash_main_node_profiler draft_node_profiler;
|
||||
if (dflash_draft_node_timing) {
|
||||
draft_node_profiler.profile = dflash_profile;
|
||||
draft_node_profiler.prev_callback = lctx.cparams.cb_eval;
|
||||
draft_node_profiler.prev_user_data = lctx.cparams.cb_eval_user_data;
|
||||
ggml_backend_sched_set_eval_callback(lctx.sched, llama_dflash_main_node_eval_callback, &draft_node_profiler);
|
||||
}
|
||||
llama_graph_compute(lctx, gf, n_threads);
|
||||
if (dflash_draft_node_timing) {
|
||||
ggml_backend_sched_set_eval_callback(lctx.sched, lctx.cparams.cb_eval, lctx.cparams.cb_eval_user_data);
|
||||
}
|
||||
if (dflash_decode_timing) {
|
||||
llama_synchronize(&lctx);
|
||||
dflash_profile->decode_sync_profile_points++;
|
||||
|
|
|
|||
Loading…
Reference in New Issue