Skip to content

Commit 23231ad

Browse files
committed
Fix hot-path heap allocs + LLAMA_MAX_SEQ loop waste in KV cache
H1: Move unordered_map declarations outside per-stream loop in set_input_kq_mask_impl — .clear() preserves bucket/vector capacity instead of free+realloc on every stream iteration M3: Replace LLAMA_MAX_SEQ (256) loop bounds with seq_to_stream.size() in apply_ubatch and set_input_kq_mask_impl — for typical chat with 1-4 sequences, saves ~252 unnecessary iterations per call
1 parent 3bd5a33 commit 23231ad

1 file changed

Lines changed: 11 additions & 6 deletions

File tree

src/llama-kv-cache.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,8 +1086,9 @@ llama_kv_cache::slot_info llama_kv_cache::find_slot(const llama_ubatch & ubatch,
10861086
void llama_kv_cache::apply_ubatch(const slot_info & sinfo, const llama_ubatch & ubatch) {
10871087
// keep track of the max sequence position that we would overwrite with this ubatch
10881088
// for non-SWA cache, this would be always empty
1089+
const uint32_t n_seq = (uint32_t)seq_to_stream.size();
10891090
llama_seq_id seq_pos_max_rm[LLAMA_MAX_SEQ];
1090-
for (uint32_t s = 0; s < LLAMA_MAX_SEQ; ++s) {
1091+
for (uint32_t s = 0; s < n_seq; ++s) {
10911092
seq_pos_max_rm[s] = -1;
10921093
}
10931094

@@ -1131,7 +1132,7 @@ void llama_kv_cache::apply_ubatch(const slot_info & sinfo, const llama_ubatch &
11311132
// note: we want to preserve the invariant that all positions between [pos_min, pos_max] for each sequence
11321133
// will be present in the cache. so we have to purge any position which is less than those we would overwrite
11331134
// ref: https://github.com/ggml-org/llama.cpp/pull/13746#issuecomment-2916057092
1134-
for (uint32_t s = 0; s < LLAMA_MAX_SEQ; ++s) {
1135+
for (uint32_t s = 0; s < n_seq; ++s) {
11351136
if (seq_pos_max_rm[s] == -1) {
11361137
continue;
11371138
}
@@ -1516,19 +1517,23 @@ static void set_input_kq_mask_impl(const args_set_input_kq_mask & args, T * data
15161517
const T mask_drop = llama_cast<T>(-INFINITY);
15171518

15181519
// the min position in the batch for each sequence
1520+
const uint32_t n_seq = (uint32_t)seq_to_stream.size();
15191521
llama_pos seq_pos_min[LLAMA_MAX_SEQ];
1520-
std::fill(seq_pos_min, seq_pos_min + LLAMA_MAX_SEQ, INT32_MAX);
1522+
std::fill(seq_pos_min, seq_pos_min + n_seq, INT32_MAX);
15211523

15221524
for (uint32_t i = 0; i < ubatch->n_tokens; ++i) {
15231525
const llama_seq_id seq_id = ubatch->seq_id[i][0];
15241526

15251527
seq_pos_min[seq_id] = std::min(seq_pos_min[seq_id], ubatch->pos[i]);
15261528
}
15271529

1530+
// track the first token per sequence for mask reuse (reused across streams to avoid reallocation)
1531+
std::unordered_map<llama_seq_id, uint32_t> seq_srct;
1532+
std::unordered_map<llama_seq_id, std::vector<uint32_t>> seq_idxs;
1533+
15281534
for (uint32_t s = 0; s < n_stream; ++s) {
1529-
// track the first token per sequence for mask reuse
1530-
std::unordered_map<llama_seq_id, uint32_t> seq_srct;
1531-
std::unordered_map<llama_seq_id, std::vector<uint32_t>> seq_idxs;
1535+
seq_srct.clear();
1536+
seq_idxs.clear();
15321537

15331538
for (uint32_t ii = 0; ii < n_tps; ++ii) {
15341539
const uint32_t i = s*n_tps + ii;

0 commit comments

Comments
 (0)