| 135 | return Status{}; |
| 136 | } |
| 137 | void ClMatMulLowpNativeKernel::configure(const ClCompileContext &compile_context, |
| 138 | ITensorInfo *lhs, |
| 139 | ITensorInfo *rhs, |
| 140 | ITensorInfo *bias, |
| 141 | ITensorInfo *dst, |
| 142 | const MatMulKernelInfo &matmul_kernel_info, |
| 143 | const ActivationLayerInfo &act_info) |
| 144 | { |
| 145 | ARM_COMPUTE_ERROR_ON_NULLPTR(lhs, rhs, dst, &compile_context, &matmul_kernel_info); |
| 146 | ARM_COMPUTE_LOG_PARAMS(lhs, rhs, bias, dst, matmul_kernel_info); |
| 147 | ARM_COMPUTE_ERROR_THROW_ON(validate(lhs, rhs, bias, dst, matmul_kernel_info)); |
| 148 | |
| 149 | // dst tensor auto initialization if not yet initialized |
| 150 | auto_init_if_empty(*dst, lhs->clone()->set_tensor_shape(misc::shape_calculator::compute_matmul_shape( |
| 151 | lhs->tensor_shape(), rhs->tensor_shape(), matmul_kernel_info))); |
| 152 | |
| 153 | const int m = dst->dimension(1); |
| 154 | const int n = dst->dimension(0); |
| 155 | const int k = matmul_kernel_info.adj_lhs ? lhs->tensor_shape().y() : lhs->tensor_shape().x(); |
| 156 | const bool adj_lhs = matmul_kernel_info.adj_lhs; |
| 157 | |
| 158 | int m0 = adj_lhs ? adjust_vec_size(matmul_kernel_info.m0, m) : std::min(matmul_kernel_info.m0, m); |
| 159 | int n0 = adjust_vec_size(matmul_kernel_info.n0, n); |
| 160 | |
| 161 | // Configure kernel window |
| 162 | Window win = calculate_max_window(*dst, Steps(n0, m0)); |
| 163 | win = win.collapse(win, Window::DimZ); |
| 164 | IClKernel::configure_internal(win); |
| 165 | |
| 166 | // Calculate partial (store instead of load) M0 and partial N0 for the partial blocks at the end of a row/column if any. This is to avoid padding. |
| 167 | const unsigned int partial_store_m0 = m % m0; |
| 168 | const unsigned int partial_store_n0 = n % n0; |
| 169 | |
| 170 | CLBuildOptions build_opts; |
| 171 | build_opts.add_option("-DDATA_TYPE=" + get_cl_type_from_data_type(lhs->data_type())); |
| 172 | build_opts.add_option("-DM0=" + support::cpp11::to_string(m0)); |
| 173 | build_opts.add_option("-DN0=" + support::cpp11::to_string(n0)); |
| 174 | build_opts.add_option("-DK0=" + support::cpp11::to_string(matmul_kernel_info.k0)); |
| 175 | build_opts.add_option("-DPARTIAL_STORE_M0=" + support::cpp11::to_string(partial_store_m0)); |
| 176 | build_opts.add_option("-DPARTIAL_STORE_N0=" + support::cpp11::to_string(partial_store_n0)); |
| 177 | build_opts.add_option("-DK=" + support::cpp11::to_string(k)); |
| 178 | |
| 179 | const UniformQuantizationInfo lqinfo = lhs->quantization_info().uniform(); |
| 180 | const UniformQuantizationInfo rqinfo = rhs->quantization_info().uniform(); |
| 181 | const UniformQuantizationInfo dqinfo = dst->quantization_info().uniform(); |
| 182 | |
| 183 | float multiplier = lqinfo.scale * rqinfo.scale / dqinfo.scale; |
| 184 | int output_multiplier = 0; |
| 185 | int output_shift = 0; |
| 186 | arm_compute::quantization::calculate_quantized_multiplier(multiplier, &output_multiplier, &output_shift); |
| 187 | |
| 188 | build_opts.add_option("-DDST_MULTIPLIER=" + support::cpp11::to_string(output_multiplier)); |
| 189 | build_opts.add_option("-DDST_SHIFT=" + support::cpp11::to_string(output_shift)); |
| 190 | |
| 191 | // Note : Offset is not negated, unlike gemmlowp kernels |
| 192 | build_opts.add_option("-DLHS_OFFSET=" + support::cpp11::to_string(lqinfo.offset)); |
| 193 | build_opts.add_option("-DRHS_OFFSET=" + support::cpp11::to_string(rqinfo.offset)); |
| 194 | build_opts.add_option("-DDST_OFFSET=" + support::cpp11::to_string(dqinfo.offset)); |
nothing calls this directly
no test coverage detected