char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
230ea9d21
char/aliceai-t5-moe
1#include "llama-memory-hybrid-iswa.h" 2 3#include "llama-impl.h" 4#include "llama-model.h" 5#include "llama-context.h" 6 7// 8// llama_memory_hybrid_iswa 9// 10 11llama_memory_hybrid_iswa::llama_memory_hybrid_iswa ( 12const llama_model & model , 13/* attn */ 14ggml_type type_k , 15ggml_type type_v , 16bool v_trans , 17bool swa_full , 18uint32_t kv_size , 19uint32_t n_ubatch , 20uint32_t n_pad , 21/* recurrent */ 22ggml_type type_r , 23ggml_type type_s , 24uint32_t rs_size , 25/* common */ 26uint32_t n_seq_max , 27uint32_t n_rs_seq , 28bool offload , 29bool unified , 30/* layer filters */ 31const layer_filter_cb & filter_attn , 32const layer_filter_cb & filter_recr ) : 33hparams (model .hparams ), 34mem_attn (new llama_kv_cache_iswa ( 35model , 36type_k , 37type_v , 38v_trans , 39offload , 40swa_full , 41unified , 42kv_size , 43n_seq_max , 44n_ubatch , 45n_pad , 46nullptr , 47filter_attn == nullptr ? 48 [& ](int32_t il ) {return !hparams .is_recr (il ); } 49 :filter_attn , 50nullptr , 51nullptr 52 )), 53mem_recr (new llama_memory_recurrent ( 54model , 55type_r , 56type_s , 57offload , 58rs_size , 59n_seq_max , 60n_rs_seq , 61filter_recr == nullptr ? 62 [& ](int32_t il ) {return hparams .is_recr (il ); } 63 :filter_recr 64 )) {} 65 66llama_memory_context_ptr llama_memory_hybrid_iswa::init_batch (llama_batch_allocr & balloc ,uint32_t n_ubatch ,bool embd_all ) { 67do { 68balloc .split_reset (); 69 70// follow the recurrent pattern for creating the ubatch splits 71 std::vector < llama_ubatch > ubatches ; 72 73while (true) { 74llama_ubatch ubatch ; 75 76if (embd_all ) { 77// if all tokens are output, split by sequence 78ubatch = balloc .split_seq (n_ubatch ); 79 }else { 80// Use non-sequential split when KV cache is unified (needed for hellaswag/winogrande/multiple-choice) 81const bool unified = (mem_attn -> get_base ()-> get_n_stream ()== 1 ); 82 83// [TAG_RECURRENT_ROLLBACK_SPLITS] 84// the trailing (1 + n_rs_seq) tokens of each seq must stay in the same ubatch 85// so that the rollback snapshots remain valid 86const uint32_t n_rs_seq = mem_recr -> n_rs_seq ; 87 88ubatch = balloc .split_equal (n_ubatch , !unified ,n_rs_seq > 0 ?n_rs_seq + 1 :0 ); 89 } 90 91if (ubatch .n_tokens == 0 ) { 92break ; 93 } 94 95ubatches .push_back (std::move (ubatch ));// NOLINT 96 } 97 98if (balloc .get_n_used ()< balloc .get_n_tokens ()) { 99// failed to find a suitable split 100break ; 101 } 102 103// prepare the recurrent batches first 104if (!mem_recr -> prepare (ubatches )) { 105// TODO: will the recurrent cache be in an undefined context at this point? 106LLAMA_LOG_ERROR ("%s: failed to prepare recurrent ubatches\n" ,__func__ ); 107return std::make_unique < llama_memory_hybrid_iswa_context > (LLAMA_MEMORY_STATUS_FAILED_PREPARE ); 108 } 109 110// prepare the attention cache (iswa version returns both base and swa slot infos) 111auto sinfos_base = mem_attn -> get_base ()-> prepare (ubatches ); 112if (sinfos_base .empty ()) { 113LLAMA_LOG_ERROR ("%s: failed to prepare attention base ubatches\n" ,__func__ ); 114return std::make_unique < llama_memory_hybrid_iswa_context > (LLAMA_MEMORY_STATUS_FAILED_PREPARE ); 115 } 116 117auto sinfos_swa = mem_attn -> get_swa ()-> prepare (ubatches ); 118if (sinfos_swa .empty ()) { 119LLAMA_LOG_ERROR ("%s: failed to prepare attention swa ubatches\n" ,__func__ ); 120return std::make_unique < llama_memory_hybrid_iswa_context > (LLAMA_MEMORY_STATUS_FAILED_PREPARE ); 121 } 122 123return std::make_unique < llama_memory_hybrid_iswa_context > ( 124this , std::move (sinfos_base ), std::move (sinfos_swa ), std::move (ubatches )); 125 }while (false); 126 127return std::make_unique < llama_memory_hybrid_iswa_context > (LLAMA_MEMORY_STATUS_FAILED_PREPARE ); 128} 129 130llama_memory_context_ptr llama_memory_hybrid_iswa::init_full () { 131return std::make_unique < llama_memory_hybrid_iswa_context > (this ); 132} 133 134llama_memory_context_ptr llama_memory_hybrid_iswa::init_update (llama_context * lctx ,bool optimize ) { 135return std::make_unique < llama_memory_hybrid_iswa_context > (this ,lctx ,optimize ); 136} 137 138bool llama_memory_hybrid_iswa::get_can_shift ()const { 139// Shifting is trivially supported for recurrent 140return mem_attn -> get_can_shift (); 141} 142 143void llama_memory_hybrid_iswa::clear (bool data ) { 144mem_attn -> clear (data ); 145mem_recr -> clear (data ); 146} 147 148bool llama_memory_hybrid_iswa::seq_rm (llama_seq_id seq_id ,llama_pos p0 ,llama_pos p1 ) { 149// Try removing from the recurrent cache first since it may fail. If it does 150// fail, the cache will not have been mutated. 151if (!mem_recr -> seq_rm (seq_id ,p0 ,p1 )) { 152return false; 153 } 154return mem_attn -> seq_rm (seq_id ,p0 ,p1 ); 155} 156 157void llama_memory_hybrid_iswa::seq_cp (llama_seq_id seq_id_src ,llama_seq_id seq_id_dst ,llama_pos p0 ,llama_pos p1 ) { 158mem_attn -> seq_cp (seq_id_src ,seq_id_dst ,p0 ,p1 ); 159mem_recr -> seq_cp (seq_id_src ,seq_id_dst ,p0 ,p1 ); 160} 161 162void llama_memory_hybrid_iswa::seq_keep (llama_seq_id seq_id ) { 163mem_attn -> seq_keep (seq_id ); 164mem_recr -> seq_keep (seq_id ); 165} 166 167void llama_memory_hybrid_iswa::seq_add (llama_seq_id seq_id ,llama_pos p0 ,llama_pos p1 ,llama_pos shift ) { 168mem_attn -> seq_add (seq_id ,p0 ,p1 ,shift ); 169mem_recr -> seq_add (seq_id ,p0 ,p1 ,shift ); 170} 171 172void llama_memory_hybrid_iswa::seq_div (llama_seq_id seq_id ,llama_pos p0 ,llama_pos p1 ,int d ) { 173mem_attn -> seq_div (seq_id ,p0 ,p1 ,d ); 174mem_recr -> seq_div (seq_id ,p0 ,p1 ,d ); 175} 176 177llama_pos llama_memory_hybrid_iswa::seq_pos_min (llama_seq_id seq_id )const { 178// the min of the total cache is the max of the two caches' min values 179return std::max (mem_attn -> seq_pos_min (seq_id ),mem_recr -> seq_pos_min (seq_id )); 180} 181 182llama_pos llama_memory_hybrid_iswa::seq_pos_max (llama_seq_id seq_id )const { 183// the max of the total cache is the min of the two caches' max values 184return std::min (mem_attn -> seq_pos_max (seq_id ),mem_recr -> seq_pos_max (seq_id )); 185} 186 187std::map < ggml_backend_buffer_type_t ,size_t > llama_memory_hybrid_iswa::memory_breakdown ()const { 188 std::map < ggml_backend_buffer_type_t ,size_t > mb = mem_attn -> memory_breakdown (); 189for (const auto & buft_size :mem_recr -> memory_breakdown ()) { 190mb [buft_size .first ]+= buft_size .second ; 191 } 192return mb ; 193} 194 195void llama_memory_hybrid_iswa::state_write (llama_io_write_i & io ,llama_seq_id seq_id ,llama_state_seq_flags flags )const { 196mem_attn -> state_write (io ,seq_id ,flags ); 197mem_recr -> state_write (io ,seq_id ,flags ); 198} 199 200void llama_memory_hybrid_iswa::state_read (llama_io_read_i & io ,llama_seq_id seq_id ,llama_state_seq_flags flags ) { 201mem_attn -> state_read (io ,seq_id ,flags ); 202mem_recr -> state_read (io ,seq_id ,flags ); 203} 204 205llama_kv_cache_iswa * llama_memory_hybrid_iswa::get_mem_attn ()const { 206return mem_attn .get (); 207} 208 209llama_memory_recurrent * llama_memory_hybrid_iswa::get_mem_recr ()const { 210return mem_recr .get (); 211} 212 213// 214// llama_memory_hybrid_iswa_context 215// 216 217llama_memory_hybrid_iswa_context::llama_memory_hybrid_iswa_context (llama_memory_status status ) :status (status ) {} 218 219llama_memory_hybrid_iswa_context::llama_memory_hybrid_iswa_context (llama_memory_hybrid_iswa * mem ) : 220ctx_attn (mem -> get_mem_attn ()-> init_full ()), 221ctx_recr (mem -> get_mem_recr ()-> init_full ()), 222status (llama_memory_status_combine (ctx_attn -> get_status (),ctx_recr -> get_status ())) { 223} 224 225llama_memory_hybrid_iswa_context::llama_memory_hybrid_iswa_context ( 226llama_memory_hybrid_iswa * mem , 227llama_context * lctx , 228bool optimize ) : 229ctx_attn (mem -> get_mem_attn ()-> init_update (lctx ,optimize )), 230ctx_recr (mem -> get_mem_recr ()-> init_update (lctx ,optimize )), 231status (llama_memory_status_combine (ctx_attn -> get_status (),ctx_recr -> get_status ())) { 232} 233 234llama_memory_hybrid_iswa_context::llama_memory_hybrid_iswa_context ( 235llama_memory_hybrid_iswa * mem , 236slot_info_vec_t sinfos_base , 237slot_info_vec_t sinfos_swa , 238 std::vector < llama_ubatch > ubatches ) : 239ubatches (std::move (ubatches )), 240// note: here we copy the ubatches. not sure if this is ideal 241ctx_attn (new llama_kv_cache_iswa_context (mem -> get_mem_attn (), std::move (sinfos_base ), std::move (sinfos_swa ),this -> ubatches )), 242ctx_recr (new llama_memory_recurrent_context (mem -> get_mem_recr (),this -> ubatches )), 243status (llama_memory_status_combine (ctx_attn -> get_status (),ctx_recr -> get_status ())) { 244} 245 246bool llama_memory_hybrid_iswa_context::next () { 247assert (status == LLAMA_MEMORY_STATUS_SUCCESS ); 248 249ctx_attn -> next (); 250ctx_recr -> next (); 251 252if (++ i_next >=ubatches .size ()) { 253return false; 254 } 255 256return true; 257} 258 259bool llama_memory_hybrid_iswa_context::apply () { 260assert (!llama_memory_status_is_fail (status )); 261 262bool res = true; 263 264res = res & ctx_attn -> apply (); 265res = res & ctx_recr -> apply (); 266 267return res ; 268} 269 270llama_memory_status llama_memory_hybrid_iswa_context::get_status ()const { 271return status ; 272} 273 274const llama_ubatch & llama_memory_hybrid_iswa_context::get_ubatch ()const { 275assert (status == LLAMA_MEMORY_STATUS_SUCCESS ); 276return ubatches [i_next ]; 277} 278 279const llama_kv_cache_iswa_context * llama_memory_hybrid_iswa_context::get_attn ()const { 280return static_cast < const llama_kv_cache_iswa_context *> (ctx_attn .get ()); 281} 282 283const llama_memory_recurrent_context * llama_memory_hybrid_iswa_context::get_recr ()const { 284return static_cast < const llama_memory_recurrent_context *> (ctx_recr .get ()); 285}