| 114 | CpuGemmLowpMatrixMultiplyCore::~CpuGemmLowpMatrixMultiplyCore() = default; |
| 115 | |
| 116 | void CpuGemmLowpMatrixMultiplyCore::configure( |
| 117 | const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, ITensorInfo *dst, const GEMMInfo &gemm_info) |
| 118 | { |
| 119 | ARM_COMPUTE_TRACE_EVENT(ARM_COMPUTE_PROF_CAT_CPU, ARM_COMPUTE_PROF_LVL_CPU, |
| 120 | "CpuGemmLowpMatrixMultiplyCore::configure"); |
| 121 | ARM_COMPUTE_ERROR_ON_NULLPTR(a, b, dst); |
| 122 | ARM_COMPUTE_ERROR_THROW_ON(CpuGemmLowpMatrixMultiplyCore::validate(a, b, c, dst, gemm_info)); |
| 123 | ARM_COMPUTE_LOG_PARAMS(a, b, c, dst, gemm_info); |
| 124 | |
| 125 | const ITensorInfo *matrix_a = a; |
| 126 | const ITensorInfo *matrix_b = b; |
| 127 | GEMMInfo info = gemm_info; |
| 128 | |
| 129 | // Set internal variables |
| 130 | _a_offset = a->quantization_info().uniform().offset; |
| 131 | _b_offset = b->quantization_info().uniform().offset; |
| 132 | _run_vector_matrix_multiplication = a->dimension(1) < 2; |
| 133 | _reshape_b_only_on_first_run = b->are_values_constant(); |
| 134 | _is_prepared = false; |
| 135 | _fused_assembly_path = false; |
| 136 | _flip_signedness = is_data_type_quantized_per_channel(b->data_type()) && (a->data_type() == DataType::QASYMM8) && |
| 137 | _reshape_b_only_on_first_run; |
| 138 | _gemm_info = gemm_info; |
| 139 | |
| 140 | // F32 dequant path? (input quantized, output float) |
| 141 | const bool dequantize_f32 = int8_dequantize_f32_path(a->data_type(), dst->data_type()); |
| 142 | |
| 143 | const ITensorInfo *a_to_use = a; |
| 144 | // Initialize assembly kernel meta-data |
| 145 | cpu::AsmGemmInfo asm_info = init_assembly_metadata(gemm_info); |
| 146 | if (dequantize_f32) |
| 147 | { |
| 148 | // We don't want arm_gemm to compute the activations because bias and offsets are added in ACL at a later step |
| 149 | // so we disable activation in arm_gemm and run it as a post op in ACL |
| 150 | asm_info.activation_info = arm_compute::ActivationLayerInfo(); |
| 151 | } |
| 152 | |
| 153 | const int32_t offset_correction = 128; |
| 154 | const DataType dt = DataType::QASYMM8_SIGNED; |
| 155 | const UniformQuantizationInfo iqinfo = a_to_use->quantization_info().uniform(); |
| 156 | |
| 157 | _signed_a = a_to_use->clone()->set_data_type(dt).set_quantization_info( |
| 158 | QuantizationInfo(iqinfo.scale, iqinfo.offset + offset_correction)); |
| 159 | |
| 160 | // If inputs are mixed-sign but this machine does not support mixed sign kernels, |
| 161 | // flip the sign so matched-sign kernels can be used. |
| 162 | if (!_flip_signedness && a->data_type() == DataType::QASYMM8 && b->data_type() == DataType::QASYMM8_SIGNED && |
| 163 | !bool(CpuGemmAssemblyDispatch::validate(a_to_use, b, c, dst, asm_info))) |
| 164 | { |
| 165 | _flip_signedness = true; |
| 166 | } |
| 167 | _asm_glue = std::make_unique<cpu::CpuGemmAssemblyDispatch>(); |
| 168 | |
| 169 | // Convert to QASYMM8 -> QASYMM8_SIGNED and back |
| 170 | if (_flip_signedness) |
| 171 | { |
| 172 | _convert_to_signed_asymm = std::make_unique<kernels::CpuConvertQuantizedSignednessKernel>(); |
| 173 | _convert_to_signed_asymm->configure(a_to_use, &_signed_a); |
nothing calls this directly
no test coverage detected