#pragma once #include "llama-impl.h" #include "llama-cparams.h" #include "llama-sampling.h" #include "llama-spec-features.h" struct llama_model; #include #include #include #include struct llama_kv_cell { llama_pos pos = -1; llama_pos delta = 0; int32_t src = 0; // used by recurrent state models to copy states std::set seq_id; bool has_seq_id(const llama_seq_id & id) const { return seq_id.find(id) != seq_id.end(); } bool is_empty() const { return seq_id.empty(); } bool is_same_seq(const llama_kv_cell & other) const { return seq_id == other.seq_id; } }; // ring-buffer of cached KV data struct llama_kv_cache { bool has_shift = false; bool do_defrag = false; bool do_copy = false; bool recurrent = false; // with recurrent state models, a cell can hold the state for more than one past token bool hybrid = false; bool v_trans = true; // the value tensor is transposed // Note: The value of head isn't only used to optimize searching // for a free KV slot. llama_decode_internal also uses it, so it // cannot be freely changed after a slot has been allocated. uint32_t head = 0; uint32_t size = 0; uint32_t used = 0; // used cells (i.e. at least one seq_id) // computed before each graph build uint32_t n = 0; ggml_type type_k = GGML_TYPE_F16; ggml_type type_v = GGML_TYPE_F16; std::vector cells; std::vector k_l; // per layer std::vector v_l; std::vector s_l; // per layer recurrent state storage (Qwen3Next) // DSA lightning-indexer key cache (GLM-5.2 / DeepSeek-V3.2). One per layer, MQA single // head: [indexer_head_size, kv_size]. Mirrors k_l but stores the (Hadamard-rotated) // indexer keys so a decoded token scores against ALL past indexer keys, not just the // current batch. Empty unless the model has the DSA indexer. std::vector kr_l; // When true, the delta_net graph builder will enable per-step SSM state saves bool save_per_step_ssm = false; std::vector split_k_l; std::vector split_v_l; std::vector split_s_l; // Per-device replicas of the MLA compressed-latent KV cache (-sm graph for DEEPSEEK2/GLM_DSA/MISTRAL4). std::vector replicated_k_l; std::vector ctxs; std::vector bufs; size_t total_size() const { size_t size = 0; for (ggml_backend_buffer_t buf : bufs) { size += ggml_backend_buffer_get_size(buf); } return size; } // GPU-resident checkpoint for recurrent/hybrid speculative decoding struct gpu_checkpoint { std::vector cells_snapshot; uint32_t head_snapshot = 0; uint32_t used_snapshot = 0; std::vector s_l_shadow; std::vector> split_s_l_shadow; // Per-step SSM state checkpoints for speculative decoding. std::vector> per_step_ssm; // Per-step conv feature buffer: stores qkv_mixed features from the // verification forward pass so conv state can be reconstructed at any step. // One tensor per recurrent layer, each sized [conv_dim * max_tokens]. //std::vector> per_step_qkv; std::vector> per_step_conv; int32_t per_step_n_tokens = 0; int32_t per_step_max_allocated = 0; int64_t per_step_ssm_state_size = 0; int64_t per_step_conv_state_dim = 0; int64_t per_step_conv_dim = 0; int32_t per_step_d_conv = 0; int selected_spec_mode = -1; int fixed_spec_mode = LLAMA_SPEC_CKPT_NONE; int32_t fixed_max_tokens = 0; // Serialised sequence state for CPU mode std::vector cpu_state_data; // Separate storage for per-step allocations std::vector per_step_ctxs; std::vector per_step_bufs; std::vector shadow_ctxs; std::vector shadow_bufs; bool allocated = false; bool shadow_conv_only = false; bool saved = false; ~gpu_checkpoint() { for (struct ggml_context * ctx : shadow_ctxs) { ggml_free(ctx); } for (ggml_backend_buffer_t buf : shadow_bufs) { ggml_backend_buffer_free(buf); } for (struct ggml_context * ctx : per_step_ctxs) { ggml_free(ctx); } for (ggml_backend_buffer_t buf : per_step_bufs) { ggml_backend_buffer_free(buf); } } }; gpu_checkpoint ckpt; bool checkpoint_alloc_shadows(bool conv_only_shadow = false); bool checkpoint_supported() const; bool checkpoint_save(ggml_backend_sched_t sched); bool checkpoint_restore(ggml_backend_sched_t sched); void checkpoint_delete(); // Per-step checkpoint: allocate, restore step k's full state (SSM + conv) to cache bool per_step_alloc(const llama_model & model, int max_tokens); bool per_step_restore(const llama_model & model, ggml_backend_sched_t sched, int step); ~llama_kv_cache() { for (struct ggml_context * ctx : ctxs) { ggml_free(ctx); } for (ggml_backend_buffer_t buf : bufs) { ggml_backend_buffer_free(buf); } } }; struct llama_control_vector { std::vector tensors; // per layer std::vector ctxs; std::vector bufs; int32_t layer_start = -1; int32_t layer_end = -1; struct ggml_tensor * tensor_for(int il) const { if (il < 0 || il < layer_start || il > layer_end || (size_t) il >= tensors.size()) { return nullptr; } return tensors[il]; } struct ggml_tensor * apply_to(struct ggml_context * ctx, struct ggml_tensor * cur, int il) const { ggml_tensor * layer_dir = tensor_for(il); if (layer_dir != nullptr) { cur = ggml_add(ctx, cur, layer_dir); } return cur; } ~llama_control_vector() { for (struct ggml_context * ctx : ctxs) { ggml_free(ctx); } for (ggml_backend_buffer_t buf : bufs) { ggml_backend_buffer_free(buf); } } }; struct llama_context { llama_context(const llama_model & model); ~llama_context(); const struct llama_model & model; struct llama_cparams cparams; struct llama_sampling sampling; struct llama_kv_cache kv_self; struct llama_context * mtp_target_ctx = nullptr; struct llama_control_vector cvec; std::vector scale_data; std::unordered_map lora_adapters; std::vector backends; #ifdef GGML_USE_METAL ggml_backend_t backend_metal = nullptr; #endif ggml_backend_t backend_cpu = nullptr; bool has_evaluated_once = false; int64_t t_start_us; int64_t t_load_us; int64_t t_p_eval_us = 0; int64_t t_eval_us = 0; int64_t t_compute_start_us = 0; int64_t n_queued_tokens = 0; int32_t n_p_eval = 0; // number of tokens in eval calls for the prompt (with batch size > 1) int32_t n_eval = 0; // number of eval calls // host buffer for the model output (logits and embeddings) ggml_backend_buffer_t buf_output = nullptr; // decode output (2-dimensional array: [n_outputs][n_vocab]) size_t logits_size = 0; // capacity (of floats) for logits float * logits = nullptr; std::vector output_ids; // map batch token positions to ids of the logits and embd buffers size_t output_size = 0; // capacity (of tokens positions) for the output buffers int32_t n_outputs = 0; // number of actually-used outputs in the current ubatch or last logical batch int32_t n_outputs_embd = 0; // number of embedding rows produced for the current logical batch bool logits_all = false; // embeddings output (2-dimensional array: [n_outputs][n_embd]) // populated only when pooling_type == LLAMA_POOLING_TYPE_NONE size_t embd_size = 0; // capacity (of floats) for embeddings float * embd = nullptr; // sequence embeddings output (map of [n_embd] vectors) // populated only when pooling_type != LLAMA_POOLING_TYPE_NONE std::map> embd_seq; // whether we are computing encoder output or decoder output bool is_encoding = false; // output of the encoder part of the encoder-decoder models std::vector embd_enc; std::vector> seq_ids_enc; // memory buffers used to evaluate the model std::vector buf_compute_meta; ggml_backend_sched_t sched = nullptr; ggml_abort_callback abort_callback = nullptr; void * abort_callback_data = nullptr; const float * draft_input_hidden_state = nullptr; size_t draft_input_hidden_state_n_floats = 0; std::vector draft_input_hidden_state_owned; struct dflash_runtime { struct target_window_state { const float * features = nullptr; size_t features_n_floats = 0; int32_t features_n_rows = 0; const float * append_features = nullptr; size_t append_features_n_floats = 0; int32_t append_features_n_rows = 0; const llama_pos * positions = nullptr; size_t positions_n = 0; uint64_t version = 0; int32_t keep_rows = 0; int32_t append_rows = 0; bool replace = false; std::vector features_owned; std::vector append_features_owned; std::vector positions_owned; std::vector features_padded; std::vector pos_ctx_data; std::vector kq_mask_data; std::vector kq_mask_swa_data; }; struct kv_runtime_state { std::vector k_ctx_cache; std::vector v_ctx_cache; struct ggml_context * cache_ctx = nullptr; std::vector cache_bufs; std::vector cache_pos; std::vector cache_slot_valid; int32_t cache_write_pos = 0; int32_t cache_n_filled = 0; int32_t cache_update_rows = 0; int32_t cache_reserved_rows = 0; int32_t cache_view_write_pos = 0; int32_t cache_view_n_filled = 0; uint64_t cache_applied_window_version = 0; bool cache_valid = false; bool cache_view_valid = false; std::vector cache_compute_meta; ggml_backend_sched_t cache_sched = nullptr; ggml_cgraph * cache_graph = nullptr; int32_t cache_graph_rows = 0; int32_t cache_graph_write_pos = 0; struct ggml_tensor * cache_input_target_features = nullptr; struct ggml_tensor * cache_input_pos_ctx = nullptr; struct ggml_tensor * kq_mask_tensor = nullptr; struct ggml_tensor * kq_mask_swa_tensor = nullptr; struct ggml_tensor * draft_tail_rows_tensor = nullptr; }; struct capture_state { std::vector layer_ids; std::vector> layer_rows; int32_t row_count = 0; int32_t row_width = 0; uint64_t capture_batch_id = 0; std::vector layer_seen_batch_id; ggml_backend_sched_eval_callback prev_cb_eval = nullptr; void * prev_cb_eval_user_data = nullptr; }; struct input_state { struct ggml_tensor * target_features = nullptr; // F32 [n_target_features, cross_ctx] struct ggml_tensor * pos_ctx = nullptr; // I32 [cross_ctx] struct ggml_tensor * kq_mask = nullptr; // F32 [cross_ctx + n_batch, GGML_PAD(n_batch)] struct ggml_tensor * kq_mask_swa = nullptr; // F32 [cross_ctx + n_batch, GGML_PAD(n_batch)] }; target_window_state target; kv_runtime_state kv; std::unique_ptr capture; std::vector feature_view_buffer; input_state inputs; int32_t visible_cross_ctx = 0; // Argmax token IDs from the DFlash draft graph, computed via GPU argmax. // Populated in llama_decode_internal after graph compute. std::vector draft_tokens; struct ggml_tensor * draft_tokens_tensor = nullptr; }; dflash_runtime dflash; using dflash_capture_state = dflash_runtime::capture_state; // input tensors struct ggml_tensor * inp_tokens; // I32 [n_batch] struct ggml_tensor * inp_embd; // F32 [n_embd, n_batch] struct ggml_tensor * inp_pos; // I32 [n_batch] struct ggml_tensor * inp_out_ids; // I32 [n_outputs] struct ggml_tensor * inp_KQ_mask; // F32 [kv_size, n_batch] struct ggml_tensor * inp_KQ_mask_swa; // F32 [kv_size, n_batch] struct ggml_tensor * inp_K_shift; // I32 [kv_size] struct ggml_tensor * inp_mean; // F32 [n_batch, n_batch] struct ggml_tensor * inp_cls; // I32 [n_batch] struct ggml_tensor * inp_s_copy; // I32 [kv_size] struct ggml_tensor * inp_s_mask; // F32 [1, n_kv] struct ggml_tensor * inp_s_seq; // I32 [n_kv, n_batch] struct ggml_tensor * inp_s_seq_qnext; // I32 [1, n_batch] struct ggml_tensor * inp_pos_bucket; // I32 [n_batch|n_kv, n_batch] struct ggml_tensor * inp_embd_enc; // F32 [n_embd, n_outputs_enc] struct ggml_tensor * inp_KQ_mask_cross; // F32 [n_outputs_enc, n_batch] struct ggml_tensor * inp_scale = nullptr; // F32 [n_tokens] struct ggml_tensor * inp_mtp_states = nullptr; struct ggml_tensor * inp_dsa_sink = nullptr; // F32 [n_kv, n_tokens] per-sequence attention-sink boost for DSA indexer top-k struct ggml_tensor * inp_mask_inf = nullptr; ggml_backend_t ggml_backend_by_name(const char * name); struct Prev; std::unique_ptr prev; std::unique_ptr prev_mtp; void reset_scheduler(); bool can_reuse_graph(const llama_batch & u_batch); struct CacheCopy { ggml_tensor * cpy = nullptr; size_t step = 0; }; std::vector cache_copies; // GLM-DSA lightning indexer: the indexer-key cache (kr_l) write is a separate ggml_cpy that // the K/V cache_copies fixup does NOT cover. Under graph reuse (FA pads KV to 256, so n_kv // stays constant across consecutive decode ubatches and the graph IS reused) its view_offs // would stay baked at the first ubatch's kv_head, scattering this ubatch's indexer keys to a // stale slot. Later ubatches never populate their own recent index-key cells (those cells read // uninitialized -> wrong block-max-pool/top-k -> degraded/NaN sparse-FA decode). Register the // kr_l cpy per layer here and patch its offset in update_cache_copies(), exactly like K/V. std::vector dsa_cache_copies; bool update_cache_copies(); bool ensure_dflash_kv_cache_tensors(int32_t cross_ctx); void free_dflash_kv_cache_tensors(); bool prepare_mtp_graph_inputs( struct llama_context & lctx); void set_mtp_op_type(llama_mtp_op_type value); int max_nodes(int n_tokens, int n_kv) const; };