| 560 | } |
| 561 | |
| 562 | llama_kv_cache::slot_info_vec_t llama_kv_cache::prepare(const std::vector<llama_ubatch> & ubatches) { |
| 563 | llama_kv_cache::slot_info_vec_t res; |
| 564 | |
| 565 | struct state_t { |
| 566 | slot_info sinfo; // slot info for the ubatch |
| 567 | |
| 568 | std::vector<uint32_t> v_heads_old; // old positions of the heads, before placing the ubatch |
| 569 | |
| 570 | std::vector<llama_kv_cells> v_cells; // copy of the old cells, before placing the ubatch |
| 571 | }; |
| 572 | |
| 573 | // remember the old state of the cells so we can restore it in the end |
| 574 | std::vector<state_t> states; |
| 575 | |
| 576 | bool success = true; |
| 577 | |
| 578 | for (const auto & ubatch : ubatches) { |
| 579 | // only find a suitable slot for the ubatch. don't modify the cells yet |
| 580 | const auto sinfo_new = find_slot(ubatch, false); |
| 581 | if (sinfo_new.empty()) { |
| 582 | success = false; |
| 583 | break; |
| 584 | } |
| 585 | |
| 586 | // remeber the position that we found |
| 587 | res.push_back(sinfo_new); |
| 588 | |
| 589 | // store the old state of the cells in the recovery stack |
| 590 | { |
| 591 | state_t state = { sinfo_new, v_heads, {} }; |
| 592 | |
| 593 | for (uint32_t s = 0; s < sinfo_new.n_stream(); ++s) { |
| 594 | auto & cells = v_cells[sinfo_new.strm[s]]; |
| 595 | |
| 596 | state.v_cells.push_back(cells.cp(sinfo_new.idxs[s])); |
| 597 | } |
| 598 | |
| 599 | states.push_back(std::move(state)); |
| 600 | } |
| 601 | |
| 602 | // now emplace the ubatch |
| 603 | apply_ubatch(sinfo_new, ubatch); |
| 604 | } |
| 605 | |
| 606 | GGML_ASSERT(!states.empty() || !success); |
| 607 | |
| 608 | // iterate backwards and restore the cells to their original state |
| 609 | for (auto it = states.rbegin(); it != states.rend(); ++it) { |
| 610 | const auto & sinfo = it->sinfo; |
| 611 | |
| 612 | for (uint32_t s = 0; s < sinfo.n_stream(); ++s) { |
| 613 | auto & cells = v_cells[sinfo.strm[s]]; |
| 614 | auto & head = v_heads[sinfo.strm[s]]; |
| 615 | |
| 616 | cells.set(sinfo.idxs[s], it->v_cells[s]); |
| 617 | head = it->v_heads_old[s]; |
| 618 | } |
| 619 | } |
no test coverage detected