| 632 | } |
| 633 | |
| 634 | void ConvCache::update(CactusGraph* gb, size_t layer, const size_t bx_node) { |
| 635 | if (layer >= num_layers || !bx_node || window_size == 0 || hidden_size == 0) { |
| 636 | return; |
| 637 | } |
| 638 | |
| 639 | auto& state = layer_states[layer]; |
| 640 | const void* output_ptr = gb->get_output(bx_node); |
| 641 | if (!output_ptr) { |
| 642 | return; |
| 643 | } |
| 644 | |
| 645 | const auto& buffer = gb->get_output_buffer(bx_node); |
| 646 | const size_t stride_bytes = hidden_size * element_size; |
| 647 | |
| 648 | size_t rows = 1; |
| 649 | if (!buffer.shape.empty()) { |
| 650 | if (buffer.shape.size() == 1) { |
| 651 | rows = 1; |
| 652 | } else { |
| 653 | rows = buffer.shape[0]; |
| 654 | } |
| 655 | } |
| 656 | |
| 657 | if (buffer.total_size > 0 && hidden_size > 0) { |
| 658 | size_t inferred = buffer.total_size / hidden_size; |
| 659 | if (inferred > 0) { |
| 660 | rows = inferred; |
| 661 | } |
| 662 | } |
| 663 | |
| 664 | if (rows == 0) { |
| 665 | return; |
| 666 | } |
| 667 | |
| 668 | size_t copy_rows = std::min(rows, window_size); |
| 669 | size_t start_row = rows > window_size ? rows - window_size : 0; |
| 670 | |
| 671 | const uint8_t* src = static_cast<const uint8_t*>(output_ptr) + start_row * stride_bytes; |
| 672 | |
| 673 | for (size_t i = 0; i < copy_rows; ++i) { |
| 674 | std::memcpy(state.data.data() + state.head * stride_bytes, src + i * stride_bytes, stride_bytes); |
| 675 | state.head = (state.head + 1) % window_size; |
| 676 | if (state.count < window_size) { |
| 677 | ++state.count; |
| 678 | } |
| 679 | } |
| 680 | } |
| 681 | |
| 682 | void ConvCache::reset() { |
| 683 | for (auto& state : layer_states) { |
no test coverage detected