// // Copyright © 2017 Arm Ltd. All rights reserved. // See LICENSE file in the project root for full license information. // #include "NeonWorkloadFactory.hpp" #include "armnn/Utils.hpp" #include "CpuTensorHandle.hpp" #include "Layer.hpp" #ifdef ARMCOMPUTENEON_ENABLED #include "arm_compute/runtime/Allocator.h" #include "MemCopyWorkload.hpp" #include "NeonTensorHandle.hpp" #include "NeonWorkloadUtils.hpp" #include "NeonWorkloads.hpp" #endif #include "MakeWorkloadHelper.hpp" #include namespace armnn { bool NeonWorkloadFactory::IsLayerSupported(const Layer& layer, DataType dataType, std::string& outReasonIfUnsupported) { return IWorkloadFactory::IsLayerSupported(Compute::CpuAcc, layer, dataType, outReasonIfUnsupported); } #ifdef ARMCOMPUTENEON_ENABLED NeonWorkloadFactory::NeonWorkloadFactory() : m_MemoryManager(std::make_unique()) { } std::unique_ptr NeonWorkloadFactory::CreateSubTensorHandle(ITensorHandle& parent, TensorShape const& subTensorShape, unsigned int const* subTensorOrigin) const { BOOST_ASSERT(parent.GetType() == ITensorHandle::Neon); const arm_compute::TensorShape shape = armcomputetensorutils::BuildArmComputeTensorShape(subTensorShape); arm_compute::Coordinates coords; coords.set_num_dimensions(subTensorShape.GetNumDimensions()); for (unsigned int i = 0; i < subTensorShape.GetNumDimensions(); i++) { // arm compute indexes tensor coords in reverse order unsigned int revertedIndex = subTensorShape.GetNumDimensions() - i - 1; coords.set(i, boost::numeric_cast(subTensorOrigin[revertedIndex])); } return std::make_unique(boost::polymorphic_downcast(&parent)->GetTensor(), shape, coords); } std::unique_ptr NeonWorkloadFactory::CreateTensorHandle(const TensorInfo& tensorInfo) const { return std::make_unique(tensorInfo); } std::unique_ptr NeonWorkloadFactory::CreateInput(const InputQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info); } std::unique_ptr NeonWorkloadFactory::CreateOutput(const OutputQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info); } std::unique_ptr NeonWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info); } std::unique_ptr NeonWorkloadFactory::CreateSoftmax(const SoftmaxQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info, m_MemoryManager.Get()); } std::unique_ptr NeonWorkloadFactory::CreateSplitter(const SplitterQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info); } std::unique_ptr NeonWorkloadFactory::CreateMerger(const MergerQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info); } std::unique_ptr NeonWorkloadFactory::CreateFullyConnected( const FullyConnectedQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info, m_MemoryManager.Get()); } std::unique_ptr NeonWorkloadFactory::CreatePermute(const PermuteQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info); } std::unique_ptr NeonWorkloadFactory::CreatePooling2d(const Pooling2dQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info); } std::unique_ptr NeonWorkloadFactory::CreateConvolution2d( const Convolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info, m_MemoryManager.Get()); } std::unique_ptr NeonWorkloadFactory::CreateDepthwiseConvolution2d( const DepthwiseConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload( descriptor, info); } std::unique_ptr NeonWorkloadFactory::CreateNormalization( const NormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info, m_MemoryManager.Get()); } std::unique_ptr NeonWorkloadFactory::CreateAddition(const AdditionQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info); } std::unique_ptr NeonWorkloadFactory::CreateMultiplication( const MultiplicationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info); } std::unique_ptr NeonWorkloadFactory::CreateBatchNormalization( const BatchNormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info); } std::unique_ptr NeonWorkloadFactory::CreateMemCopy(const MemCopyQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (descriptor.m_Inputs.empty() || !descriptor.m_Inputs[0]) { throw InvalidArgumentException("NeonWorkloadFactory: Invalid null input for MemCopy workload"); } // Create a workload that will copy tensor data from the inputs, which can have a number of different formats, // to Neon tensors. switch (descriptor.m_Inputs[0]->GetType()) { case ITensorHandle::Cpu: return MakeWorkload(descriptor, info); #if ARMCOMPUTECL_ENABLED case ITensorHandle::CL: { return MakeWorkload(descriptor, info); } #endif default: throw InvalidArgumentException("NeonWorkloadFactory: Destination type not supported for MemCopy Workload."); } } std::unique_ptr NeonWorkloadFactory::CreateResizeBilinear( const ResizeBilinearQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateFakeQuantization( const FakeQuantizationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateL2Normalization(const L2NormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info, m_MemoryManager.Get()); } std::unique_ptr NeonWorkloadFactory::CreateConstant(const ConstantQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info); } std::unique_ptr NeonWorkloadFactory::CreateReshape(const ReshapeQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info); } std::unique_ptr NeonWorkloadFactory::CreateFloor(const FloorQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info); } void NeonWorkloadFactory::Finalize() { m_MemoryManager.Finalize(); } #else // Compiled without ArmCompute libs NeonWorkloadFactory::NeonWorkloadFactory() { } std::unique_ptr NeonWorkloadFactory::CreateSubTensorHandle(ITensorHandle& parent, TensorShape const& subTensorShape, unsigned int const* subTensorOrigin) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateTensorHandle(const TensorInfo& tensorInfo) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateInput(const InputQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateOutput(const OutputQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateSoftmax(const SoftmaxQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateSplitter(const SplitterQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateMerger(const MergerQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateFullyConnected(const FullyConnectedQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreatePermute(const PermuteQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreatePooling2d(const Pooling2dQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateConvolution2d(const Convolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateDepthwiseConvolution2d( const DepthwiseConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateNormalization(const NormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateAddition(const AdditionQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateBatchNormalization(const BatchNormalizationQueueDescriptor& data, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateMultiplication(const MultiplicationQueueDescriptor& data, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateMemCopy(const MemCopyQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateResizeBilinear(const ResizeBilinearQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateFakeQuantization( const FakeQuantizationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateL2Normalization(const L2NormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateConstant(const ConstantQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateReshape(const ReshapeQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } std::unique_ptr NeonWorkloadFactory::CreateFloor(const FloorQueueDescriptor& descriptor, const WorkloadInfo& info) const { return nullptr; } void NeonWorkloadFactory::Finalize() {} #endif } //namespace armnn