/** Copyright (c) 2018 ARM Limited.** SPDX-License-Identifier: MIT** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to* deal in the Software without restriction, including without limitation the* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or* sell copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:** The above copyright notice and this permission notice shall be included in all* copies or substantial portions of the Software.** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE* SOFTWARE.*/#include "arm_compute/runtime/CL/functions/CLWinogradConvolutionLayer.h"#include "arm_compute/core/CL/ICLTensor.h"#include "arm_compute/core/Utils.h"#include "arm_compute/core/Validate.h"#include "arm_compute/core/utils/misc/ShapeCalculator.h"#include "arm_compute/runtime/CL/CLScheduler.h"using namespace arm_compute;namespace{Size2D winograd_output_tile(const Size2D &input_dims, const Size2D &kernel_dims){Size2D output_tile = Size2D{};if(kernel_dims == Size2D(3U, 3U)){output_tile = (input_dims.width <= 4 && input_dims.height <= 4) ? Size2D(2U, 2U) : Size2D(4U, 4U);}else if(kernel_dims == Size2D(5U, 5U)){output_tile = Size2D(4U, 4U);}return output_tile;}bool check_support_fast_math(const Size2D &output_tile, const Size2D &kernel_size){// Check if we want to configure a Winograd configuration which requires fast mathusing WinogradConfiguration = std::pair<std::pair<int, int>, std::pair<int, int>>;std::vector<WinogradConfiguration> fast_math_winograd ={WinogradConfiguration(std::pair<int, int>(4, 4), std::pair<int, int>(5, 5))};auto p = std::make_pair(std::pair<int, int>(output_tile.width, output_tile.height),std::pair<int, int>(kernel_size.width, kernel_size.height));return std::find(fast_math_winograd.begin(), fast_math_winograd.end(), p) != fast_math_winograd.end();}} // namespaceCLWinogradConvolutionLayer::CLWinogradConvolutionLayer(std::shared_ptr<IMemoryManager> memory_manager): _memory_group(memory_manager), _batched_mm(memory_manager), _input_transform(), _filter_transform(), _output_transform(), _activationlayer_function(), _input0(), _input1(), _batched_mm_output(),_original_weights(nullptr), _is_prepared(false), _is_activationlayer_enabled(false){}void CLWinogradConvolutionLayer::configure(ICLTensor *input, const ICLTensor *weights, const ICLTensor *biases, ICLTensor *output, const PadStrideInfo &conv_info, const ActivationLayerInfo &act_info,bool enable_fast_math){// Get indices for the width and heightconst size_t idx_width = get_data_layout_dimension_index(input->info()->data_layout(), DataLayoutDimension::WIDTH);const size_t idx_height = get_data_layout_dimension_index(input->info()->data_layout(), DataLayoutDimension::HEIGHT);// Input shape, kernel size and output tileconst Size2D input_dims = Size2D(input->info()->tensor_shape()[idx_width], input->info()->tensor_shape()[idx_height]);const Size2D kernel_size = Size2D(weights->info()->tensor_shape()[idx_width], weights->info()->tensor_shape()[idx_height]);const Size2D output_tile = winograd_output_tile(input_dims, kernel_size);// Check if the Winograd configuration requires fast mathif(!enable_fast_math){ARM_COMPUTE_ERROR_ON_MSG(check_support_fast_math(output_tile, kernel_size), "This Winograd configuration requires enable_fast_math=true");}const WinogradInfo winograd_info = WinogradInfo(output_tile,kernel_size,input_dims,conv_info,input->info()->data_layout());_is_prepared = false;_original_weights = weights;// Manage intermediate tensors_memory_group.manage(&_input0);_memory_group.manage(&_batched_mm_output);// Do not manage _input1 as it contains the weights// Configure input transform_input_transform.configure(input, &_input0, winograd_info);// Configure filter transform_filter_transform.configure(weights, &_input1, winograd_info);// Configure batched matrix multiply_batched_mm.configure(&_input0, &_input1, nullptr, &_batched_mm_output, 1.0f, 0.0f, GEMMInfo(false, false, true /* Reshape weights only for the first run*/));// Configure output transform_output_transform.configure(&_batched_mm_output, biases, output, winograd_info);// Configure activation layer_is_activationlayer_enabled = act_info.enabled();if(_is_activationlayer_enabled){_activationlayer_function.configure(output, nullptr, act_info);}// Allocate temporary tensors_input0.allocator()->allocate();_batched_mm_output.allocator()->allocate();}Status CLWinogradConvolutionLayer::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info,const ActivationLayerInfo &act_info, bool enable_fast_math){// Get indeces for the width and heightconst size_t idx_width = get_data_layout_dimension_index(input->data_layout(), DataLayoutDimension::WIDTH);const size_t idx_height = get_data_layout_dimension_index(input->data_layout(), DataLayoutDimension::HEIGHT);// Input shape, kernel size and output tileconst Size2D input_dims = Size2D(input->tensor_shape()[idx_width], input->tensor_shape()[idx_height]);const Size2D kernel_size = Size2D(weights->tensor_shape()[idx_width], weights->tensor_shape()[idx_height]);const Size2D output_tile = winograd_output_tile(input_dims, kernel_size);// Check if the Winograd configuration requires fast mathif(!enable_fast_math){ARM_COMPUTE_RETURN_ERROR_ON_MSG(check_support_fast_math(output_tile, kernel_size), "This Winograd configuration requires enable_fast_math=true");}const WinogradInfo winograd_info = WinogradInfo(output_tile,kernel_size,input_dims,conv_info,input->data_layout());// Validate input transformconst TensorShape input0_shape = misc::shape_calculator::compute_winograd_input_transform_shape(*input, winograd_info);const TensorInfo input0 = input->clone()->set_tensor_shape(input0_shape);ARM_COMPUTE_RETURN_ON_ERROR(CLWinogradInputTransform::validate(input, &input0, winograd_info));// Validate filter transformconst TensorShape input1_shape = misc::shape_calculator::compute_winograd_filter_transform_shape(*weights, winograd_info);const TensorInfo input1 = weights->clone()->set_tensor_shape(input1_shape);ARM_COMPUTE_RETURN_ON_ERROR(CLWinogradFilterTransformKernel::validate(weights, &input1, winograd_info));// Validate batched matrix multiplyTensorShape batched_mm_output_shape = input0.tensor_shape();batched_mm_output_shape[0] = input1.tensor_shape()[0];const TensorInfo batched_mm_output = input0.clone()->set_tensor_shape(batched_mm_output_shape);ARM_COMPUTE_RETURN_ON_ERROR(CLGEMM::validate(&input0, &input1, nullptr, &batched_mm_output, 1.0f, 0.0f, GEMMInfo(false, false, true /* Reshape weights only for the first run*/)));// Configure output transformARM_COMPUTE_RETURN_ON_ERROR(CLWinogradOutputTransformKernel::validate(&batched_mm_output, biases, output, winograd_info));// Validate Activation Layerif(act_info.enabled()){ARM_COMPUTE_RETURN_ON_ERROR(CLActivationLayer::validate(output, nullptr, act_info));}return Status{};}void CLWinogradConvolutionLayer::run(){prepare();_memory_group.acquire();// Run input transform_input_transform.run();// Run batched matrix multiplication_batched_mm.run();// Run output transformCLScheduler::get().enqueue(_output_transform);if(_is_activationlayer_enabled){_activationlayer_function.run();}_memory_group.release();}void CLWinogradConvolutionLayer::prepare(){if(!_is_prepared){// Run filter transform and mark original weights as unused_input1.allocator()->allocate();CLScheduler::get().enqueue(_filter_transform, false);_original_weights->mark_as_unused();// Prepare GEMM and release reshaped weights if marked unused by CLGEMM_batched_mm.prepare();if(!_input1.is_used()){_input1.allocator()->free();}CLScheduler::get().queue().finish();_is_prepared = true;}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。