| 186 | } |
| 187 | |
| 188 | void ClGemmConv2d::configure(const CLCompileContext &compile_context, |
| 189 | ITensorInfo *src, |
| 190 | ITensorInfo *weights, |
| 191 | ITensorInfo *biases, |
| 192 | ITensorInfo *dst, |
| 193 | const Conv2dInfo &conv2d_info, |
| 194 | const WeightsInfo &weights_info) |
| 195 | { |
| 196 | ARM_COMPUTE_ERROR_ON_NULLPTR(src, weights, dst); |
| 197 | |
| 198 | ARM_COMPUTE_ERROR_THROW_ON(ClGemmConv2d::validate(src, weights, biases, dst, conv2d_info, weights_info)); |
| 199 | ARM_COMPUTE_LOG_PARAMS(src, weights, biases, dst, conv2d_info, weights_info); |
| 200 | |
| 201 | const DataType data_type = src->data_type(); |
| 202 | const DataLayout data_layout = src->data_layout(); |
| 203 | const int idx_width = get_data_layout_dimension_index(data_layout, DataLayoutDimension::WIDTH); |
| 204 | const int idx_height = get_data_layout_dimension_index(data_layout, DataLayoutDimension::HEIGHT); |
| 205 | const int idx_kernels = get_data_layout_dimension_index(data_layout, DataLayoutDimension::BATCHES); |
| 206 | |
| 207 | const unsigned int kernel_width = weights->dimension(idx_width); |
| 208 | const unsigned int kernel_height = weights->dimension(idx_height); |
| 209 | const unsigned int num_kernels = weights->dimension(idx_kernels); |
| 210 | |
| 211 | const UniformQuantizationInfo iq_info = src->quantization_info().uniform(); |
| 212 | const UniformQuantizationInfo oq_info = dst->quantization_info().uniform(); |
| 213 | |
| 214 | _is_prepared = weights_info.retain_internal_weights(); |
| 215 | _is_quantized = is_data_type_quantized_asymmetric(src->data_type()); |
| 216 | _skip_im2col = (data_layout == DataLayout::NHWC && kernel_width == 1 && kernel_height == 1 && |
| 217 | conv2d_info.conv_info.stride().first == 1 && conv2d_info.conv_info.stride().second == 1) && |
| 218 | !conv2d_info.conv_info.has_padding(); |
| 219 | _skip_col2im = data_layout == DataLayout::NHWC; |
| 220 | |
| 221 | // Only for quantize there are few cases where we cannot fuse the activation function in GEMM |
| 222 | _fuse_activation = true; |
| 223 | |
| 224 | const ITensorInfo *gemm_input_to_use = src; |
| 225 | ITensorInfo *gemm_output_to_use = dst; |
| 226 | |
| 227 | // Get parameters from conv_info |
| 228 | unsigned int stride_x = 0; |
| 229 | unsigned int stride_y = 0; |
| 230 | std::tie(stride_x, stride_y) = conv2d_info.conv_info.stride(); |
| 231 | |
| 232 | // Get convolved dimensions |
| 233 | unsigned int conv_w = 0; |
| 234 | unsigned int conv_h = 0; |
| 235 | std::tie(conv_w, conv_h) = scaled_dimensions(src->dimension(idx_width), src->dimension(idx_height), kernel_width, |
| 236 | kernel_height, conv2d_info.conv_info, conv2d_info.dilation); |
| 237 | |
| 238 | unsigned int mat_weights_cols = num_kernels / conv2d_info.num_groups; |
| 239 | |
| 240 | ITensorInfo *biases_to_use = biases; |
| 241 | _append_bias = false; |
| 242 | |
| 243 | _weights_reshape_kernel = std::make_unique<kernels::ClWeightsReshapeKernel>(); |
| 244 | if (conv2d_info.num_groups != 1 && biases != nullptr) |
| 245 | { |
no test coverage detected