| 172 | CpuWinogradConv2d::~CpuWinogradConv2d() = default; |
| 173 | |
| 174 | void CpuWinogradConv2d::configure(const ITensorInfo *src, |
| 175 | const ITensorInfo *weights, |
| 176 | const ITensorInfo *biases, |
| 177 | ITensorInfo *dst, |
| 178 | const PadStrideInfo &conv_info, |
| 179 | const ActivationLayerInfo &act_info, |
| 180 | bool enable_fast_math) |
| 181 | { |
| 182 | ARM_COMPUTE_TRACE_EVENT(ARM_COMPUTE_PROF_CAT_CPU, ARM_COMPUTE_PROF_LVL_CPU, "CpuWinogradConv2d::configure"); |
| 183 | ARM_COMPUTE_ERROR_ON_NULLPTR(src, weights, dst); |
| 184 | ARM_COMPUTE_ERROR_THROW_ON(validate(src, weights, biases, dst, conv_info, act_info, enable_fast_math)); |
| 185 | ARM_COMPUTE_LOG_PARAMS(src, weights, biases, dst, conv_info, act_info, enable_fast_math); |
| 186 | ARM_COMPUTE_UNUSED(biases); |
| 187 | const DataType data_type = src->data_type(); |
| 188 | uint32_t nthreads = NEScheduler::get().num_threads(); |
| 189 | _data_layout = src->data_layout(); |
| 190 | const Tensor4DShape kernel_shape{internal_get_shape(weights)}; |
| 191 | |
| 192 | bool success = get_winograd_kernel_implementation(src, weights, dst, conv_info, act_info, enable_fast_math, |
| 193 | &_winograd_impl, _conv_args); |
| 194 | |
| 195 | ARM_COMPUTE_EXIT_ON_MSG_VAR(!success, "Unsupported kernel size: %d x %d.\n", kernel_shape.n_rows, |
| 196 | kernel_shape.n_cols); |
| 197 | ARM_COMPUTE_LOG_MSG_WITH_FORMAT_ACL(arm_compute::logging::LogLevel::INFO, "Using input transform: %s\n", |
| 198 | _winograd_impl.input_transform->get_name().c_str()); |
| 199 | ARM_COMPUTE_LOG_MSG_WITH_FORMAT_ACL(arm_compute::logging::LogLevel::INFO, "Using weight transform: %s\n", |
| 200 | _winograd_impl.input_transform->get_name().c_str()); |
| 201 | ARM_COMPUTE_LOG_MSG_WITH_FORMAT_ACL(arm_compute::logging::LogLevel::INFO, "Using output transform: %s\n", |
| 202 | _winograd_impl.input_transform->get_name().c_str()); |
| 203 | |
| 204 | const bool has_impl = ((_winograd_impl.input_transform != nullptr) && |
| 205 | (_winograd_impl.output_transform != nullptr) && (_winograd_impl.gemm_args != nullptr)); |
| 206 | if (has_impl) |
| 207 | { |
| 208 | // Determine how much working space is required, allocate it. |
| 209 | const size_t input_workspace_size = |
| 210 | _winograd_impl.input_transform->get_working_space_size(*_conv_args, nthreads); |
| 211 | const size_t output_workspace_size = |
| 212 | _winograd_impl.output_transform->get_working_space_size(*_conv_args, nthreads); |
| 213 | |
| 214 | TensorInfo input_workspace_info(TensorShape(input_workspace_size), 1, DataType::U8); |
| 215 | TensorInfo output_workspace_info(TensorShape(output_workspace_size), 1, DataType::U8); |
| 216 | _input_workspace = input_workspace_info; |
| 217 | _output_workspace = output_workspace_info; |
| 218 | |
| 219 | const auto &wds = _winograd_impl.winograd_spec; |
| 220 | |
| 221 | // Preparing winograd transformed input tensor |
| 222 | const size_t data_type_size = src->element_size(); |
| 223 | const uint32_t m = _winograd_impl.gemm_args->_Msize; // Total number of tiles |
| 224 | const uint32_t k = _winograd_impl.gemm_args->_Ksize; // Input channels |
| 225 | const uint32_t n = _winograd_impl.gemm_args->_Nsize; // Output channels |
| 226 | const uint32_t n_gemms = _winograd_impl.gemm_args->_nmulti; |
| 227 | const uint32_t n_batches = _winograd_impl.gemm_args->_nbatches; |
| 228 | constexpr size_t storage_alignment = 64; |
| 229 | |
| 230 | const TensorShape a_shape(k, m, n_batches, n_gemms); |
| 231 | Strides a_strides(data_type_size); |
nothing calls this directly
no test coverage detected