| 560 | |
| 561 | template <typename TypeInput, typename TypeWeight, typename TypeOutput, class OutputStage> |
| 562 | void Fallback<TypeInput, TypeWeight, TypeOutput, OutputStage>::prepare(ITensorPack &tensors) |
| 563 | { |
| 564 | if (!_is_prepared) |
| 565 | { |
| 566 | auto b = tensors.get_const_tensor(TensorType::ACL_SRC_1); |
| 567 | auto c = tensors.get_const_tensor(TensorType::ACL_SRC_2); |
| 568 | ARM_COMPUTE_ERROR_ON_NULLPTR(b); |
| 569 | |
| 570 | // Setup up matrix bias in the assembly kernel, it's just a pointer to matrix C. |
| 571 | if (c && c->info()->data_type() == DataType::S32) |
| 572 | { |
| 573 | _gemm_kernel_asm->set_quantized_bias( |
| 574 | reinterpret_cast<const int32_t *>(c->buffer() + c->info()->offset_first_element_in_bytes()), 0); |
| 575 | } |
| 576 | const ITensor *b_to_use = b; |
| 577 | |
| 578 | // Pre-pretranspose B if required |
| 579 | CpuAuxTensorHandler pre_pretransposed_b( |
| 580 | offset_int_vec(PrePretransposedB), _pre_pretransposed_b_info, tensors, |
| 581 | /*pack_inject: no need to inject into tensors*/ |
| 582 | false, |
| 583 | /*bypass_alloc: no need to allocate if pre-pretranspose B is not required as this handle will not be used*/ |
| 584 | !_run_pre_pretranspose_b); |
| 585 | |
| 586 | if (_run_pre_pretranspose_b) |
| 587 | { |
| 588 | ARM_COMPUTE_ERROR_ON(_pre_pretranspose_b == nullptr); |
| 589 | ITensorPack pre_pretranspose_pack{{ACL_SRC, b_to_use}, {ACL_DST, pre_pretransposed_b.get()}}; |
| 590 | _pre_pretranspose_b->run(pre_pretranspose_pack); |
| 591 | b_to_use = pre_pretransposed_b.get(); |
| 592 | } |
| 593 | |
| 594 | // Pretranspose B if required |
| 595 | if (_B_pretranspose_required) |
| 596 | { |
| 597 | // Fixed format kernels need no pretranspose. |
| 598 | ARM_COMPUTE_ERROR_ON(arm_compute::is_fixed_format( |
| 599 | assembly_utils::map_to_arm_compute_weight_format(_gemm_kernel_asm->get_config().weight_format))); |
| 600 | const int ldb = b_to_use->info()->strides_in_bytes().y() / b_to_use->info()->element_size(); |
| 601 | const auto in1_ptr = reinterpret_cast<const TypeWeight *>( |
| 602 | b_to_use->buffer() + b_to_use->info()->offset_first_element_in_bytes()); |
| 603 | const int multi_stride_b = b_to_use->info()->strides_in_bytes().z() / b_to_use->info()->element_size(); |
| 604 | |
| 605 | CpuAuxTensorHandler pretranspose(offset_int_vec(Pretranspose), _pretranspose_info, tensors, false); |
| 606 | |
| 607 | ARM_COMPUTE_ERROR_ON(pretranspose.get()->buffer() == nullptr); |
| 608 | |
| 609 | const bool kernel_supports_transpose = _gemm_kernel_asm->B_pretranspose_supports_transpose(); |
| 610 | run_parallel_pretranspose_B_array<TypeInput, TypeWeight, TypeOutput>( |
| 611 | _gemm_kernel_asm.get(), pretranspose.get(), in1_ptr, ldb, multi_stride_b, |
| 612 | NEScheduler::get().num_threads(), _B_pre_pretranspose_required && kernel_supports_transpose); |
| 613 | |
| 614 | b->mark_as_unused(); |
| 615 | // Note that we don't need to mark b_to_use as unused, as if it's been assigned to pre_pretransposed_b, |
| 616 | // its memory will be auto-managed by the handler |
| 617 | } |
| 618 | |
| 619 | if (_gemm_info.method == AsmConvMethod::Indirect) |
nothing calls this directly
no test coverage detected