| 290 | } |
| 291 | |
| 292 | void llama_kv_cache::seq_cp(llama_seq_id seq_id_src, llama_seq_id seq_id_dst, llama_pos p0, llama_pos p1) { |
| 293 | GGML_ASSERT(seq_id_src >= 0 && (size_t) seq_id_src < seq_to_stream.size()); |
| 294 | GGML_ASSERT(seq_id_dst >= 0 && (size_t) seq_id_dst < seq_to_stream.size()); |
| 295 | |
| 296 | const auto s0 = seq_to_stream[seq_id_src]; |
| 297 | const auto s1 = seq_to_stream[seq_id_dst]; |
| 298 | |
| 299 | if (s0 == s1) { |
| 300 | // since both sequences are in the same stream, no data copy is necessary |
| 301 | // we just have to update the cells meta data |
| 302 | |
| 303 | auto & cells = v_cells[s0]; |
| 304 | |
| 305 | if (seq_id_src == seq_id_dst) { |
| 306 | return; |
| 307 | } |
| 308 | |
| 309 | if (p0 < 0) { |
| 310 | p0 = 0; |
| 311 | } |
| 312 | |
| 313 | if (p1 < 0) { |
| 314 | p1 = std::numeric_limits<llama_pos>::max(); |
| 315 | } |
| 316 | |
| 317 | for (uint32_t i = 0; i < cells.size(); ++i) { |
| 318 | if (!cells.pos_in(i, p0, p1)) { |
| 319 | continue; |
| 320 | } |
| 321 | |
| 322 | if (cells.seq_has(i, seq_id_src)) { |
| 323 | cells.seq_add(i, seq_id_dst); |
| 324 | } |
| 325 | } |
| 326 | |
| 327 | return; |
| 328 | } |
| 329 | |
| 330 | // cross-stream sequence copies require to copy the actual buffer data |
| 331 | |
| 332 | bool is_full = true; |
| 333 | |
| 334 | if (p0 > 0 && p0 + 1 < (int) get_size()) { |
| 335 | is_full = false; |
| 336 | } |
| 337 | |
| 338 | if (p1 > 0 && p1 + 1 < (int) get_size()) { |
| 339 | is_full = false; |
| 340 | } |
| 341 | |
| 342 | GGML_ASSERT(is_full && "seq_cp() is only supported for full KV buffers"); |
| 343 | |
| 344 | // enqueue the copy operation - the buffer copy will be performed during the next update |
| 345 | sc_info.ssrc.push_back(s0); |
| 346 | sc_info.sdst.push_back(s1); |
| 347 | |
| 348 | v_cells[s1].reset(); |
| 349 | for (uint32_t i = 0; i < v_cells[s0].size(); ++i) { |
no test coverage detected