| 875 | } |
| 876 | |
| 877 | void ClGemmLowpMatrixMultiplyCore::prepare(ITensorPack &tensors) |
| 878 | { |
| 879 | if (!_is_prepared) |
| 880 | { |
| 881 | auto b = tensors.get_const_tensor(TensorType::ACL_SRC_1); |
| 882 | CLAuxTensorHandler tmp_b(offset_int_vec(RhsReshape), _tmp_b, tensors, true); |
| 883 | CLAuxTensorHandler vec_sum_col(offset_int_vec(VecSumCol), _vector_sum_col, tensors, true); |
| 884 | CLAuxTensorHandler rhs_qasymm8(offset_int_vec(RhsQAsymm8), _qasymm8_weights, tensors, false); |
| 885 | |
| 886 | ARM_COMPUTE_ERROR_ON_NULLPTR(b); |
| 887 | |
| 888 | if (_convert_to_qasymm8) |
| 889 | { |
| 890 | ITensorPack convert_to_qs8_pack = {{ACL_SRC, b}, {ACL_DST, rhs_qasymm8.get()}}; |
| 891 | CLScheduler::get().enqueue_op(*_weights_to_qasymm8, convert_to_qs8_pack, false); |
| 892 | b->mark_as_unused(); |
| 893 | } |
| 894 | |
| 895 | if (is_gemm_reshaped(_gemm_kernel_type) && _reshape_b_only_on_first_run) |
| 896 | { |
| 897 | // Run reshape kernel and mark original weights tensor as unused |
| 898 | ITensorPack mtx_b_pack = {{TensorType::ACL_SRC, _convert_to_qasymm8 ? rhs_qasymm8.get() : b}, |
| 899 | {TensorType::ACL_DST, tmp_b.get()}}; |
| 900 | CLScheduler::get().enqueue_op(*_mtx_b_reshape_kernel, mtx_b_pack, false); |
| 901 | b->mark_as_unused(); |
| 902 | } |
| 903 | |
| 904 | // Run matrix B reduction kernel only if _a_offset is not equal to 0 |
| 905 | if (_a_offset != 0 && _reshape_b_only_on_first_run) |
| 906 | { |
| 907 | ITensorPack mtx_b_red_pack = {{TensorType::ACL_SRC, _convert_to_qasymm8 ? rhs_qasymm8.get() : b}, |
| 908 | {TensorType::ACL_DST, vec_sum_col.get()}}; |
| 909 | CLScheduler::get().enqueue_op(*_mtx_b_reduction_kernel, mtx_b_red_pack, false); |
| 910 | } |
| 911 | |
| 912 | // Compute GEMM output multipliers and shifts for output stage |
| 913 | { |
| 914 | const size_t num_filters = (_gemm_info.gemmlowp_output_stage().is_quantized_per_channel) |
| 915 | ? _gemm_info.gemmlowp_output_stage().gemmlowp_multipliers.size() |
| 916 | : 1; |
| 917 | |
| 918 | CLAuxTensorHandler multipliers(offset_int_vec(Multipliers), _gemm_output_stage_multipliers, tensors, false); |
| 919 | CLAuxTensorHandler shifts(offset_int_vec(Shifts), _gemm_output_stage_shifts, tensors, false); |
| 920 | |
| 921 | ICLTensor *multiplier_tensor = multipliers.get(); |
| 922 | if (multiplier_tensor != nullptr && multiplier_tensor->info()->total_size() > 0) |
| 923 | { |
| 924 | multiplier_tensor->map(CLScheduler::get().queue(), true); |
| 925 | std::memcpy(multiplier_tensor->ptr_to_element(Coordinates(0)), |
| 926 | _gemm_info.gemmlowp_output_stage().gemmlowp_multipliers.data(), |
| 927 | num_filters * sizeof(int32_t)); |
| 928 | multiplier_tensor->unmap(CLScheduler::get().queue()); |
| 929 | } |
| 930 | |
| 931 | ICLTensor *shifts_tensor = shifts.get(); |
| 932 | if (shifts.get() != nullptr && shifts_tensor->info()->total_size() > 0) |
| 933 | { |
| 934 | shifts_tensor->map(CLScheduler::get().queue(), true); |
nothing calls this directly
no test coverage detected