char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
b356fa262
char/aliceai-t5-moe
1#pragma once 2 3#include "llama.h" 4#include "llama-cparams.h" 5 6#include <bitset> 7#include <cassert> 8#include <cstring> 9#include <limits> 10#include <set> 11#include <vector> 12 13struct llama_kv_cell_ext { 14// 2D spatial positions, typically used for M-RoPE 15llama_pos x = 0 ; 16llama_pos y = 0 ; 17 18// when tok = LLAMA_TOKEN_NULL when the cell is produced by embedding input (i.e. multimodal) 19// use case: n-gram embeddings hash 20llama_token tok = LLAMA_TOKEN_NULL ; 21 22// return true if the current 2D spatial position is greater than other 23bool is_2d_gt (llama_pos ox ,llama_pos oy )const { 24return (y > oy )|| (y == oy && x > ox ); 25 } 26 27void reset () { 28static_assert (std ::is_trivially_copyable_v < llama_kv_cell_ext > ); 29 30* this = llama_kv_cell_ext {}; 31 } 32}; 33 34// meta information about KV cells that can be part of multiple sequences at the same time 35// TODO: add unit tests 36class llama_kv_cells { 37public : 38using seq_set_t = std ::bitset < LLAMA_MAX_SEQ > ; 39 40void reset () { 41for (uint32_t i = 0 ;i < pos .size ();++ i ) { 42pos [i ]= -1 ; 43ext [i ].reset (); 44shift [i ]= 0 ; 45seq [i ].reset (); 46 } 47 48has_shift = false; 49 50used .clear (); 51 52for (uint32_t s = 0 ;s < LLAMA_MAX_SEQ ;++ s ) { 53seq_pos [s ].clear (); 54 } 55 } 56 57void reset_shift () { 58has_shift = false; 59 60for (uint32_t i = 0 ;i < shift .size ();++ i ) { 61shift [i ]= 0 ; 62 } 63 } 64 65uint32_t size ()const { 66return pos .size (); 67 } 68 69void resize (uint32_t n ) { 70pos .resize (n ); 71ext .resize (n ); 72shift .resize (n ); 73seq .resize (n ); 74 75reset (); 76 } 77 78bool is_empty (uint32_t i )const { 79assert (i < pos .size ()); 80assert ((pos [i ]< 0 && pos [i ]== -1 )|| pos [i ] >=0 ); 81 82return pos [i ]== -1 ; 83 } 84 85uint32_t get_used ()const { 86return used .size (); 87 } 88 89// the index of the first cell that is used 90// return 0 if no cells are used 91uint32_t used_min ()const { 92return used .empty () ?0 :* used .begin (); 93 } 94 95// the index of the last cell that is used + 1 96// return 0 if no cells are used 97uint32_t used_max_p1 ()const { 98return used .empty () ?0 :* used .rbegin ()+ 1 ; 99 } 100 101bool get_has_shift ()const { 102return has_shift ; 103 } 104 105// move cell isrc to idst (used during defrag) 106//void mv(uint32_t isrc, uint32_t idst) { 107// assert(isrc < pos.size()); 108// assert(idst < pos.size()); 109 110// assert(pos[idst] == -1); 111// assert(pos[isrc] != -1); 112 113// pos [idst] = pos [isrc]; 114// shift[idst] = shift[isrc]; 115// seq [idst] = seq [isrc]; 116 117// pos [isrc] = -1; 118// shift[isrc] = 0; 119// seq [isrc].reset(); 120 121// used.erase (isrc); 122// used.insert(idst); 123//} 124 125// copy the state of cells [i, i + n) (used for save/restore the state of the cells) 126llama_kv_cells cp (uint32_t i ,uint32_t n )const { 127assert (i + n <=pos .size ()); 128 129llama_kv_cells res ; 130 131res .resize (n ); 132 133for (uint32_t j = 0 ;j < n ;++ j ) { 134const autoidx = i + j; 135 136res. pos [j] = pos[idx]; 137res. ext [j] = ext[idx]; 138res. seq [j] = seq[idx]; 139 140assert (shift[idx] == 0 ); 141} 142 143return res; 144} 145 146// copy the state of cells [idxs[0], idxs[1], ..., idxs[idxs.size() - 1]) 147llama_kv_cells cp ( const std ::vector < uint32_t > & idxs) const { 148llama_kv_cells res; 149 150res. resize (idxs. size ()); 151 152for ( uint32_t j = 0 ; j < idxs. size (); ++ j) { 153const auto idx = idxs[j]; 154 155res. pos [j] = pos[idx]; 156res. ext [j] = ext[idx]; 157res. seq [j] = seq[idx]; 158 159assert (shift[idx] == 0 ); 160} 161 162return res; 163} 164 165// set the state of cells [i, i + other.pos.size()) (used for save/restore the state of the cells) 166void set ( uint32_t i, const llama_kv_cells & other) { 167assert (i + other. pos . size () <= pos. size ()); 168 169for ( uint32_t j = 0 ; j < other. pos . size (); ++ j) { 170const auto idx = i + j; 171 172if (pos[idx] == -1 && other. pos [j] != -1 ) { 173used. insert (i + j); 174} 175 176if (pos[idx] != -1 && other. pos [j] == -1 ) { 177used. erase (i + j); 178} 179 180if (pos[idx] != -1 ) { 181seq_pos_rm (i + j); 182} 183 184pos[idx] = other. pos [j]; 185ext[idx] = other. ext [j]; 186seq[idx] = other. seq [j]; 187 188if (pos[idx] != -1 ) { 189seq_pos_add (i + j); 190} 191 192assert (shift[idx] == 0 ); 193} 194} 195 196// set the state of cells [idxs[0], idxs[1], ..., idxs[idxs.size() - 1]) 197void set ( const std ::vector < uint32_t > & idxs, const llama_kv_cells & other) { 198assert (idxs. size () == other. pos . size ()); 199 200for ( uint32_t j = 0 ; j < other. pos . size (); ++ j) { 201const auto idx = idxs[j]; 202 203if (pos[idx] == -1 && other. pos [j] != -1 ) { 204used. insert (idx); 205} 206 207if (pos[idx] != -1 && other. pos [j] == -1 ) { 208used. erase (idx); 209} 210 211if (pos[idx] != -1 ) { 212seq_pos_rm (idx); 213} 214 215pos[idx] = other. pos [j]; 216ext[idx] = other. ext [j]; 217seq[idx] = other. seq [j]; 218 219if (pos[idx] != -1 ) { 220seq_pos_add (idx); 221} 222 223assert (shift[idx] == 0 ); 224} 225} 226 227// clear a non-empty cell 228void rm ( uint32_t i) { 229assert (i < pos. size ()); 230assert (pos[i] != -1 ); 231 232seq_pos_rm (i); 233seq[i]. reset (); 234 235pos[i] = -1 ; 236ext[i]. reset (); 237shift[i] = 0 ; 238 239used. erase (i); 240} 241 242// note: call only if the cell has seq_id 243// return true if the cell becomes empty 244bool seq_rm ( uint32_t i, llama_seq_id seq_id) { 245assert (i < pos. size ()); 246assert (seq[i]. test (seq_id)); 247assert (pos[i] != -1 ); 248assert (seq_id >= 0 ); 249 250seq[i]. reset (seq_id); 251seq_pos_dec (seq_id, i); 252 253if (seq[i]. none ()) { 254pos[i] = -1 ; 255ext[i]. reset (); 256shift[i] = 0 ; 257 258used. erase (i); 259 260return true; 261} 262 263return false; 264} 265 266// return true if the cell becomes empty (i.e. it did not contain seq_id before the call) 267bool seq_keep ( uint32_t i, llama_seq_id seq_id) { 268assert (i < pos. size ()); 269 270if (seq[i]. test (seq_id)) { 271seq_pos_rm (i); 272seq[i]. reset (); 273 274seq[i]. set (seq_id); 275seq_pos_inc (seq_id, i); 276 277return false; 278} 279 280if (seq[i]. any ()) { 281seq_pos_rm (i); 282seq[i]. reset (); 283 284pos[i] = -1 ; 285ext[i]. reset (); 286shift[i] = 0 ; 287 288used. erase (i); 289 290return true; 291} 292 293assert (pos[i] == -1 ); 294 295return false; 296} 297 298// number of different sequences in the cell 299int seq_count ( uint32_t i) const { 300assert (i < pos. size ()); 301assert (pos[i] != -1 ); 302 303return seq[i]. count (); 304} 305 306// the full set of sequences this cell is visible to 307const seq_set_t & seq_get_all ( uint32_t i) const { 308assert (i < pos. size ()); 309 310return seq[i]; 311} 312 313// check if the cell contains seq_id 314bool seq_has ( uint32_t i, llama_seq_id seq_id) const { 315assert (i < pos. size ()); 316assert (seq_id >= 0 ); 317 318return seq[i]. test (seq_id); 319} 320 321// the token of the cell of sequence seq_id at the largest position <= p 322// when several cells share that position, the one with the highest index wins 323// return LLAMA_TOKEN_NULL if the sequence has no cell at or before p 324// note: used by n-gram input embeddings to recover the tokens preceding a ubatch 325llama_token seq_pos_tok_le ( llama_seq_id seq_id, llama_pos p) const { 326assert (seq_id >= 0 ); 327assert (seq_id < LLAMA_MAX_SEQ ); 328 329const auto & sp = seq_pos[seq_id]; 330 331auto it = sp. upper_bound ({ p, std::numeric_limits < uint32_t > :: max () }); 332if (it == sp. begin ()) { 333return LLAMA_TOKEN_NULL ; 334} 335 336return ext[( -- it) -> second ]. tok ; 337} 338 339// note: call only if the cell is not empty and the seq_id is not in the cell 340void seq_add ( uint32_t i, llama_seq_id seq_id) { 341assert (i < pos. size ()); 342assert (pos[i] != -1 ); 343assert (!seq[i]. test (seq_id)); 344 345seq[i]. set (seq_id); 346seq_pos_inc (seq_id, i); 347} 348 349// return the sequence id of this cell 350// note: call only for cells with exactly one sequence 351llama_seq_id seq_get ( uint32_t i) const { 352assert (seq[i]. count () == 1 ); 353 354for ( int s = 0 ; s < LLAMA_MAX_SEQ ; ++ s) { 355if (seq[i]. test (s)) { 356return s; 357} 358} 359 360return -1 ; 361} 362 363// the minimum position of sequence seq_id currently present in any of the cells 364// return -1 if the sequence is not present 365llama_pos seq_pos_min ( llama_seq_id seq_id) const { 366assert (seq_id >= 0 ); 367assert (seq_id < LLAMA_MAX_SEQ ); 368 369if (seq_pos[seq_id]. empty ()) { 370return -1 ; 371} 372 373return seq_pos[seq_id]. begin () -> first ; 374} 375 376// the maximum position of sequence seq_id currently present in any of the cells 377// return -1 if the sequence is not present 378llama_pos seq_pos_max ( llama_seq_id seq_id) const { 379assert (seq_id >= 0 ); 380assert (seq_id < LLAMA_MAX_SEQ ); 381 382if (seq_pos[seq_id]. empty ()) { 383return -1 ; 384} 385 386return seq_pos[seq_id]. rbegin () -> first ; 387} 388 389// note: call only if the cell is not empty 390llama_pos pos_get ( uint32_t i) const { 391assert (i < pos. size ()); 392assert (pos[i] != -1 ); 393 394return pos[i]; 395} 396 397const llama_kv_cell_ext & ext_get ( uint32_t i) const { 398assert (i < pos. size ()); 399assert (pos[i] != -1 ); 400 401return ext[i]; 402} 403 404// note: call only if the cell is not empty 405llama_pos get_shift ( uint32_t i) const { 406assert (i < pos. size ()); 407assert (pos[i] != -1 ); 408 409return shift[i]; 410} 411 412// check if a cell is not empty and its position is within [p0, p1) 413bool pos_in ( uint32_t i, llama_pos p0, llama_pos p1) const { 414assert (i < pos. size ()); 415 416return pos[i] >= p0 && pos[i] < p1; 417} 418 419// set the position of an empty cell 420// does not modify "has_shift" 421// note: call only if the cell is empty 422void pos_set ( uint32_t i, llama_pos p) { 423assert (i < pos. size ()); 424assert (pos[i] == -1 ); 425assert (seq[i]. none ()); 426 427pos[i] = p; 428 429used. insert (i); 430} 431 432void ext_set ( uint32_t i, llama_kv_cell_ext p) { 433assert (i < ext. size ()); 434ext[i] = p; 435} 436 437// pos[i] = pos[i] + d 438// sets "has_shift" to true 439// note: call only if the cell is not empty 440bool pos_add ( uint32_t i, llama_pos d) { 441assert (i < pos. size ()); 442assert (pos[i] != -1 ); 443 444seq_pos_rm (i); 445 446pos[i] += d; 447shift[i] += d; 448 449has_shift = true; 450 451if (pos[i] < 0 ) { 452seq[i]. reset (); 453pos[i] = -1 ; 454shift[i] = 0 ; 455 456used. erase (i); 457 458return true; 459} 460 461seq_pos_add (i); 462 463return false; 464} 465 466// pos[i] = pos[i] / d 467// sets "has_shift" to true 468// note: call only if the cell is not empty 469void pos_div ( uint32_t i, int d) { 470assert (i < pos. size ()); 471assert (pos[i] != -1 ); 472 473const llama_pos p_old = pos[i]; 474 475seq_pos_rm (i); 476 477pos[i] /= d; 478shift[i] += p_old - pos[i]; 479 480seq_pos_add (i); 481 482has_shift = true; 483} 484 485private : 486bool has_shift = false; 487 488// set of indices of used cells (i.e. pos[i] != -1, allowed to not have any seq_id) 489std ::set < uint32_t > used; 490 491std ::vector < llama_pos > pos; 492 493// stores extra info per cell 494std ::vector < llama_kv_cell_ext > ext; 495 496// this array accumulates any applied shifts to the pos array since the last reset_shift() call 497// this is used to queue multiple updates to the pos array, which in the end can be applied in one go: 498// 499// cells.pos_add(x, shift_x); 500// cells.pos_div(y, shift_y); 501// ... 502// 503// if (cells.has_shift()) { 504// for (int i = 0; i < n; ++i) { 505// auto shift_i = cells.get_shift(i); 506// ... 507// } 508// cells.reset_shift(); 509// } 510// 511std ::vector < llama_pos > shift; 512 513// the bitset seq[i] tells us which sequences are currently occupying the i-th cell 514std ::vector < seq_set_t > seq; 515 516// the set seq_pos[s] holds one (pos, cell) pair per cell that carries sequence s, ordered by position 517// this way seq_pos[s].begin() and seq_pos[s].rbegin() give us the min/max positions currently in the cache 518// and upper_bound() on a position finds the nearest cell of the sequence in logarithmic time 519// 520// the cell index is part of the key because a position can occur more than once for the same seq: 521// - during performing a cache reuse via (rm + add) 522// - some vision models have input embeddings with repeating positions 523// 524std ::set < std::pair < llama_pos, uint32_t>> seq_pos[ LLAMA_MAX_SEQ ]; 525 526// helper functions for updating `seq_pos`, once cell at a time: 527 528void seq_pos_dec ( llama_seq_id s, uint32_t i) { 529const auto n = seq_pos[s]. erase ({ pos[i], i }); 530assert (n == 1 ); 531GGML_UNUSED (n); 532} 533 534void seq_pos_inc ( llama_seq_id s, uint32_t i) { 535seq_pos[s]. insert ({ pos[i], i }); 536} 537 538// remove cell i 539void seq_pos_rm ( uint32_t i) { 540for ( int s = 0 ; s < LLAMA_MAX_SEQ ; ++ s) { 541if (seq[i]. test (s)) { 542seq_pos_dec (s, i); 543} 544} 545} 546 547// add cell i 548void seq_pos_add ( uint32_t i) { 549for ( int s = 0 ; s < LLAMA_MAX_SEQ ; ++ s) { 550if (seq[i]. test (s)) { 551seq_pos_inc (s, i); 552} 553} 554} 555}; 556 557using llama_kv_cells_vec = std::vector < llama_kv_cells > ;