Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions include/llama.h
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,21 @@ extern "C" {
// Check if the memory supports shifting
LLAMA_API bool llama_memory_can_shift(llama_memory_t mem);

// One cell holder's occupancy (Continuum fork): cells holding at least one sequence, of the cells
// it has. A composite memory reports each holder it owns by name ("attn.base", "recr").
struct llama_memory_cells_report {
char holder[32];
uint32_t used;
uint32_t size;
};

// Write up to n_max holders' occupancy into out and return how many holders the memory has (a
// return above n_max means out was too small). Read it on the thread that decodes.
LLAMA_API int32_t llama_memory_cell_usage(
llama_memory_t mem,
struct llama_memory_cells_report * out,
int32_t n_max);

//
// State / sessions
//
Expand Down
17 changes: 17 additions & 0 deletions src/llama-context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3871,6 +3871,23 @@ llama_pos llama_memory_seq_pos_max(
return mem->seq_pos_max(seq_id);
}

int32_t llama_memory_cell_usage(
llama_memory_t mem,
struct llama_memory_cells_report * out,
int32_t n_max) {
if (!mem) {
return 0;
}
const auto holders = mem->cell_usage();
for (int32_t i = 0; i < (int32_t) holders.size() && i < n_max; ++i) {
const auto & h = holders[i];
snprintf(out[i].holder, sizeof(out[i].holder), "%s", h.holder.c_str());
out[i].used = h.used;
out[i].size = h.size;
}
return (int32_t) holders.size();
}

bool llama_memory_can_shift(llama_memory_t mem) {
if (!mem) {
return false;
Expand Down
7 changes: 7 additions & 0 deletions src/llama-kv-cache-dsa-iswa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,3 +346,10 @@ const char * llama_kv_cache_dsa_iswa::training_error(const llama_batch & batch,
}
return kv_dsa->training_error(batch, flash_attn);
}

std::vector<llama_memory_cells> llama_kv_cache_dsa_iswa::cell_usage() const {
std::vector<llama_memory_cells> out;
llama_memory_cells_append(out, "dsa", kv_dsa->cell_usage());
llama_memory_cells_append(out, "swa", kv_swa->cell_usage());
return out;
}
1 change: 1 addition & 0 deletions src/llama-kv-cache-dsa-iswa.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class llama_kv_cache_dsa_iswa : public llama_memory_i {
llama_pos seq_pos_max(llama_seq_id seq_id) const override;

std::map<ggml_backend_buffer_type_t, size_t> memory_breakdown() const override;
std::vector<llama_memory_cells> cell_usage() const override;

// state write/load

Expand Down
7 changes: 7 additions & 0 deletions src/llama-kv-cache-dsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,3 +264,10 @@ const llama_kv_cache_context * llama_kv_cache_dsa_context::get_lid() const {
const char * llama_kv_cache_dsa::training_error(const llama_batch &, bool) const {
return "DSA cache row gradients are not supported";
}

std::vector<llama_memory_cells> llama_kv_cache_dsa::cell_usage() const {
std::vector<llama_memory_cells> out;
llama_memory_cells_append(out, "mla", kv_mla->cell_usage());
llama_memory_cells_append(out, "lid", kv_lid->cell_usage());
return out;
}
1 change: 1 addition & 0 deletions src/llama-kv-cache-dsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class llama_kv_cache_dsa : public llama_memory_i {
llama_pos seq_pos_max(llama_seq_id seq_id) const override;

std::map<ggml_backend_buffer_type_t, size_t> memory_breakdown() const override;
std::vector<llama_memory_cells> cell_usage() const override;

// state write/load

Expand Down
11 changes: 11 additions & 0 deletions src/llama-kv-cache-dsv4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2257,3 +2257,14 @@ const llama_kv_cache_dsv4_context::comp_plan & llama_kv_cache_dsv4_context::get_
const char * llama_kv_cache_dsv4::training_error(const llama_batch &, bool) const {
return "DSV4 cache row gradients are not supported";
}

// The compressed states (csa_state, hca_state, lid_state) are fixed rows per sequence, not cells
// that a prompt fills; only the caches below are reported.
std::vector<llama_memory_cells> llama_kv_cache_dsv4::cell_usage() const {
std::vector<llama_memory_cells> out;
llama_memory_cells_append(out, "raw", kv_raw->cell_usage());
llama_memory_cells_append(out, "csa", kv_csa->cell_usage());
llama_memory_cells_append(out, "hca", kv_hca->cell_usage());
llama_memory_cells_append(out, "lid", kv_lid->cell_usage());
return out;
}
1 change: 1 addition & 0 deletions src/llama-kv-cache-dsv4.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ class llama_kv_cache_dsv4 : public llama_memory_i {
llama_pos seq_pos_max(llama_seq_id seq_id) const override;

std::map<ggml_backend_buffer_type_t, size_t> memory_breakdown() const override;
std::vector<llama_memory_cells> cell_usage() const override;

void state_write(llama_io_write_i & io, llama_seq_id seq_id = -1, llama_state_seq_flags flags = 0) const override;
void state_read (llama_io_read_i & io, llama_seq_id seq_id = -1, llama_state_seq_flags flags = 0) override;
Expand Down
7 changes: 7 additions & 0 deletions src/llama-kv-cache-iswa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,3 +368,10 @@ const char * llama_kv_cache_iswa::training_error(const llama_batch & batch, bool
}
return kv_swa->training_error(batch, flash_attn);
}

std::vector<llama_memory_cells> llama_kv_cache_iswa::cell_usage() const {
std::vector<llama_memory_cells> out;
llama_memory_cells_append(out, "base", kv_base->cell_usage());
llama_memory_cells_append(out, "swa", kv_swa->cell_usage());
return out;
}
1 change: 1 addition & 0 deletions src/llama-kv-cache-iswa.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class llama_kv_cache_iswa : public llama_memory_i {
llama_pos seq_pos_max(llama_seq_id seq_id) const override;

std::map<ggml_backend_buffer_type_t, size_t> memory_breakdown() const override;
std::vector<llama_memory_cells> cell_usage() const override;

// state write/load

Expand Down
7 changes: 7 additions & 0 deletions src/llama-kv-cache-msa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,3 +397,10 @@ void llama_kv_cache_msa_context::set_input_pos_mask(ggml_tensor * dst, const lla
const char * llama_kv_cache_msa::training_error(const llama_batch &, bool) const {
return "MSA cache row gradients are not supported";
}

std::vector<llama_memory_cells> llama_kv_cache_msa::cell_usage() const {
std::vector<llama_memory_cells> out;
llama_memory_cells_append(out, "base", kv_base->cell_usage());
llama_memory_cells_append(out, "idx", kv_idx->cell_usage());
return out;
}
1 change: 1 addition & 0 deletions src/llama-kv-cache-msa.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class llama_kv_cache_msa : public llama_memory_i {
llama_pos seq_pos_max(llama_seq_id seq_id) const override;

std::map<ggml_backend_buffer_type_t, size_t> memory_breakdown() const override;
std::vector<llama_memory_cells> cell_usage() const override;

// state write/load

Expand Down
11 changes: 11 additions & 0 deletions src/llama-kv-cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2709,3 +2709,14 @@ const char * llama_kv_cache::training_error(const llama_batch & batch, bool flas
}
return nullptr;
}

// One holder per stream: a sequence draws only from its own stream's cells, so streams are never
// summed (a sum would report cells a request cannot use). A unified cache is one stream, one holder.
std::vector<llama_memory_cells> llama_kv_cache::cell_usage() const {
std::vector<llama_memory_cells> out;
for (size_t s = 0; s < v_cells.size(); ++s) {
const auto & cells = v_cells[s];
out.push_back({ v_cells.size() == 1 ? std::string() : "s" + std::to_string(s), cells.get_used(), cells.size() });
}
return out;
}
1 change: 1 addition & 0 deletions src/llama-kv-cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ class llama_kv_cache : public llama_memory_i {
llama_pos seq_pos_max(llama_seq_id seq_id) const override;

std::map<ggml_backend_buffer_type_t, size_t> memory_breakdown() const override;
std::vector<llama_memory_cells> cell_usage() const override;

// state write/load

Expand Down
7 changes: 7 additions & 0 deletions src/llama-memory-hybrid-iswa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,10 @@ const char * llama_memory_hybrid_iswa::training_error(const llama_batch & batch,
}
return mem_recr->training_error(batch, flash_attn);
}

std::vector<llama_memory_cells> llama_memory_hybrid_iswa::cell_usage() const {
std::vector<llama_memory_cells> out;
llama_memory_cells_append(out, "attn", mem_attn->cell_usage());
llama_memory_cells_append(out, "recr", mem_recr->cell_usage());
return out;
}
1 change: 1 addition & 0 deletions src/llama-memory-hybrid-iswa.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class llama_memory_hybrid_iswa : public llama_memory_i {
llama_pos seq_pos_max(llama_seq_id seq_id) const override;

std::map<ggml_backend_buffer_type_t, size_t> memory_breakdown() const override;
std::vector<llama_memory_cells> cell_usage() const override;

// state write/load

Expand Down
7 changes: 7 additions & 0 deletions src/llama-memory-hybrid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,3 +284,10 @@ const char * llama_memory_hybrid::training_error(const llama_batch & batch, bool
}
return mem_recr->training_error(batch, flash_attn);
}

std::vector<llama_memory_cells> llama_memory_hybrid::cell_usage() const {
std::vector<llama_memory_cells> out;
llama_memory_cells_append(out, "attn", mem_attn->cell_usage());
llama_memory_cells_append(out, "recr", mem_recr->cell_usage());
return out;
}
1 change: 1 addition & 0 deletions src/llama-memory-hybrid.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class llama_memory_hybrid : public llama_memory_i {
llama_pos seq_pos_max(llama_seq_id seq_id) const override;

std::map<ggml_backend_buffer_type_t, size_t> memory_breakdown() const override;
std::vector<llama_memory_cells> cell_usage() const override;

// state write/load

Expand Down
4 changes: 4 additions & 0 deletions src/llama-memory-recurrent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1279,3 +1279,7 @@ const char * llama_memory_recurrent::training_error(const llama_batch & batch, b
}
return nullptr;
}

std::vector<llama_memory_cells> llama_memory_recurrent::cell_usage() const {
return { { "", used, (uint32_t) cells.size() } };
}
1 change: 1 addition & 0 deletions src/llama-memory-recurrent.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class llama_memory_recurrent : public llama_memory_i {
llama_pos seq_pos_max(llama_seq_id seq_id) const override;

std::map<ggml_backend_buffer_type_t, size_t> memory_breakdown() const override;
std::vector<llama_memory_cells> cell_usage() const override;

bool prepare(const std::vector<llama_ubatch> & ubatches);

Expand Down
23 changes: 23 additions & 0 deletions src/llama-memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include "llama-graph.h"

#include <map>
#include <vector>
#include <string>
#include <memory>
#include <functional>

Expand Down Expand Up @@ -70,6 +72,24 @@ using llama_memory_context_ptr = std::unique_ptr<llama_memory_context_i>;

// general concept of LLM memory
// the KV cache is a type of LLM memory, but there can be other types
// One cell holder's occupancy: the cells holding at least one sequence, of the cells it has. A
// composite memory reports each holder it owns, its name prefixed ("attn.base", "recr"), so a
// reader sees which holder bounds what; nothing is summed across holders of different kinds.
struct llama_memory_cells {
std::string holder;
uint32_t used;
uint32_t size;
};

// Prefix every holder in `children` with `name` ("kv" -> "attn.kv" is never produced: a plain cache
// reports holder "", which becomes `name`).
inline void llama_memory_cells_append(std::vector<llama_memory_cells> & out, const char * name, std::vector<llama_memory_cells> children) {
for (auto & c : children) {
c.holder = c.holder.empty() ? std::string(name) : std::string(name) + "." + c.holder;
out.push_back(std::move(c));
}
}

struct llama_memory_i {
// this callback is used to filter out layers that should not be included in the cache
using layer_filter_cb = std::function<bool(int32_t il)>;
Expand Down Expand Up @@ -121,6 +141,9 @@ struct llama_memory_i {

virtual std::map<ggml_backend_buffer_type_t, size_t> memory_breakdown() const = 0;

// the occupancy of every cell holder this memory owns (see llama_memory_cells)
virtual std::vector<llama_memory_cells> cell_usage() const = 0;

//
// state write/read
//
Expand Down
1 change: 1 addition & 0 deletions tests/test-batch-alloc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct mock_memory : public llama_memory_i {
}

std::map<ggml_backend_buffer_type_t, size_t> memory_breakdown() const override { return {}; }
std::vector<llama_memory_cells> cell_usage() const override { return {}; } // holds no cells

void state_write(llama_io_write_i &, llama_seq_id, llama_state_seq_flags) const override { GGML_ASSERT(false && "not implemented"); }
void state_read (llama_io_read_i &, llama_seq_id, llama_state_seq_flags) override { GGML_ASSERT(false && "not implemented"); }
Expand Down
Loading
Loading