// // Copyright © 2017 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #include #include #include #include #include #include "RefWorkloadFactory.hpp" #include "RefBackendId.hpp" #include "workloads/RefWorkloads.hpp" #include "RefTensorHandle.hpp" namespace armnn { namespace { static const BackendId s_Id{RefBackendId()}; } template std::unique_ptr RefWorkloadFactory::MakeWorkload(const QueueDescriptorType& descriptor, const WorkloadInfo& info) const { return MakeWorkloadHelper (descriptor, info); } template bool IsDataType(const WorkloadInfo& info) { auto checkType = [](const TensorInfo& tensorInfo) {return tensorInfo.GetDataType() == ArmnnType;}; auto it = std::find_if(std::begin(info.m_InputTensorInfos), std::end(info.m_InputTensorInfos), checkType); if (it != std::end(info.m_InputTensorInfos)) { return true; } it = std::find_if(std::begin(info.m_OutputTensorInfos), std::end(info.m_OutputTensorInfos), checkType); if (it != std::end(info.m_OutputTensorInfos)) { return true; } return false; } bool IsSigned32(const WorkloadInfo& info) { return IsDataType(info); } bool IsBFloat16(const WorkloadInfo& info) { return IsDataType(info); } bool IsFloat16(const WorkloadInfo& info) { return IsDataType(info); } bool IsQSymmS16(const WorkloadInfo& info) { return IsDataType(info); } bool IsQSymmS8(const WorkloadInfo& info) { return IsDataType(info); } bool IsQAsymmS8(const WorkloadInfo& info) { return IsDataType(info); } bool IsQAsymmU8(const WorkloadInfo& info) { return IsDataType(info); } RefWorkloadFactory::RefWorkloadFactory(const std::shared_ptr& memoryManager) : m_MemoryManager(memoryManager) { } RefWorkloadFactory::RefWorkloadFactory() : m_MemoryManager(new RefMemoryManager()) { } const BackendId& RefWorkloadFactory::GetBackendId() const { return s_Id; } bool RefWorkloadFactory::IsLayerSupported(const Layer& layer, Optional dataType, std::string& outReasonIfUnsupported) { return IWorkloadFactory::IsLayerSupported(s_Id, layer, dataType, outReasonIfUnsupported); } bool RefWorkloadFactory::IsLayerSupported(const IConnectableLayer& layer, Optional dataType, std::string& outReasonIfUnsupported, const ModelOptions& modelOptions) { return IWorkloadFactory::IsLayerSupported(s_Id, layer, dataType, outReasonIfUnsupported, modelOptions); } std::unique_ptr RefWorkloadFactory::CreateTensorHandle(const TensorInfo& tensorInfo, const bool isMemoryManaged) const { if (isMemoryManaged) { return std::make_unique(tensorInfo, m_MemoryManager); } else { return std::make_unique(tensorInfo, static_cast(MemorySource::Malloc)); } } std::unique_ptr RefWorkloadFactory::CreateTensorHandle(const TensorInfo& tensorInfo, DataLayout dataLayout, const bool isMemoryManaged) const { // For Ref it is okay to make the TensorHandle memory managed as it can also store a pointer // to unmanaged memory. This also ensures memory alignment. IgnoreUnused(isMemoryManaged, dataLayout); if (isMemoryManaged) { return std::make_unique(tensorInfo, m_MemoryManager); } else { return std::make_unique(tensorInfo, static_cast(MemorySource::Malloc)); } } std::unique_ptr RefWorkloadFactory::CreateWorkload(LayerType type, const QueueDescriptor& descriptor, const WorkloadInfo& info) const { switch(type) { case LayerType::Activation : { auto activationQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*activationQueueDescriptor, info); } case LayerType::Addition : { auto additionQueueDescriptor = PolymorphicDowncast(&descriptor); if (info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Signed32) { return std::make_unique>(*additionQueueDescriptor, info); } else { return std::make_unique>(*additionQueueDescriptor, info); } } case LayerType::ArgMinMax : { auto argMinMaxQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*argMinMaxQueueDescriptor, info); } case LayerType::BatchNormalization : { auto batchNormQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*batchNormQueueDescriptor, info); } case LayerType::BatchToSpaceNd : { auto batchToSpaceNdQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*batchToSpaceNdQueueDescriptor, info); } case LayerType::Cast : { auto castQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*castQueueDescriptor, info); } case LayerType::ChannelShuffle : { auto channelShuffleQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*channelShuffleQueueDescriptor, info); } case LayerType::Comparison : { auto comparisonQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*comparisonQueueDescriptor, info); } case LayerType::Concat : { auto concatQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*concatQueueDescriptor, info); } case LayerType::Constant : { auto constantQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*constantQueueDescriptor, info); } case LayerType::ConvertBf16ToFp32 : { auto convertBf16ToFp32QueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*convertBf16ToFp32QueueDescriptor, info); } case LayerType::ConvertFp16ToFp32: { auto convertFp16ToFp32QueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*convertFp16ToFp32QueueDescriptor, info); } case LayerType::ConvertFp32ToBf16: { auto convertFp32ToBf16QueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*convertFp32ToBf16QueueDescriptor, info); } case LayerType::ConvertFp32ToFp16: { auto convertFp32ToFp16QueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*convertFp32ToFp16QueueDescriptor, info); } case LayerType::Convolution2d: { auto convolution2dQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*convolution2dQueueDescriptor, info); } case LayerType::Convolution3d: { auto convolution3dQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*convolution3dQueueDescriptor, info); } case LayerType::Debug: { auto debugQueueDescriptor = PolymorphicDowncast(&descriptor); if (IsBFloat16(info)) { return std::make_unique(*debugQueueDescriptor, info); } if (IsFloat16(info)) { return std::make_unique(*debugQueueDescriptor, info); } if (IsQSymmS16(info)) { return std::make_unique(*debugQueueDescriptor, info); } if (IsQSymmS8(info)) { return std::make_unique(*debugQueueDescriptor, info); } if (IsQAsymmU8(info)) { return std::make_unique(*debugQueueDescriptor, info); } if (IsQAsymmS8(info)) { return std::make_unique(*debugQueueDescriptor, info); } if (IsSigned32(info)) { return std::make_unique(*debugQueueDescriptor, info); } return MakeWorkload(*debugQueueDescriptor, info); } case LayerType::DepthToSpace: { auto depthToSpaceQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*depthToSpaceQueueDescriptor, info); } case LayerType::DepthwiseConvolution2d: { auto depthwiseConvolution2DQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*depthwiseConvolution2DQueueDescriptor, info); } case LayerType::Dequantize: { auto dequantizeQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*dequantizeQueueDescriptor, info); } case LayerType::DetectionPostProcess: { auto detectionPostProcessQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*detectionPostProcessQueueDescriptor, info); } case LayerType::Division: { auto divisionQueueDescriptor = PolymorphicDowncast(&descriptor); if (info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Signed32) { return std::make_unique>(*divisionQueueDescriptor, info); } else { return std::make_unique>(*divisionQueueDescriptor, info); } } case LayerType::ElementwiseUnary: { auto elementwiseUnaryQueueDescriptor = PolymorphicDowncast(&descriptor); if ((*elementwiseUnaryQueueDescriptor).m_Parameters.m_Operation == UnaryOperation::LogicalNot) { return std::make_unique(*elementwiseUnaryQueueDescriptor, info); } return std::make_unique(*elementwiseUnaryQueueDescriptor, info); } case LayerType::FakeQuantization: { auto fakeQuantizationQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*fakeQuantizationQueueDescriptor, info); } case LayerType::Fill: { auto fillQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*fillQueueDescriptor, info); } case LayerType::Floor: { auto floorQueueDescriptor = PolymorphicDowncast(&descriptor); if(IsQuantizedType(info.m_InputTensorInfos[0].GetDataType())) { return nullptr; } else { return std::make_unique(*floorQueueDescriptor, info); } } case LayerType::FullyConnected: { auto fullyConnectedQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*fullyConnectedQueueDescriptor, info); } case LayerType::Gather: { auto gatherQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*gatherQueueDescriptor, info); } case LayerType::Input: { auto inputQueueDescriptor = PolymorphicDowncast(&descriptor); if (info.m_InputTensorInfos.empty() ) { throw InvalidArgumentException("RefWorkloadFactory::CreateInput: Input cannot be zero length"); } if (info.m_OutputTensorInfos.empty()) { throw InvalidArgumentException("RefWorkloadFactory::CreateInput: Output cannot be zero length"); } if (info.m_InputTensorInfos[0].GetNumBytes() != info.m_OutputTensorInfos[0].GetNumBytes()) { throw InvalidArgumentException("RefWorkloadFactory::CreateInput: " "data input and output differ in byte count."); } return std::make_unique(*inputQueueDescriptor, info); } case LayerType::InstanceNormalization: { auto instanceNormalizationQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*instanceNormalizationQueueDescriptor, info); } case LayerType::L2Normalization: { auto l2NormalizationQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*l2NormalizationQueueDescriptor, info); } case LayerType::LogicalBinary: { auto logicalBinaryQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*logicalBinaryQueueDescriptor, info); } case LayerType::LogSoftmax: { auto logSoftmaxQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*logSoftmaxQueueDescriptor, info); } case LayerType::Lstm: { auto lstmQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*lstmQueueDescriptor, info); } case LayerType::Maximum: { auto maximumQueueDescriptor = PolymorphicDowncast(&descriptor); if (info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Signed32) { return std::make_unique>(*maximumQueueDescriptor, info); } else { return std::make_unique>(*maximumQueueDescriptor, info); } } case LayerType::Mean: { auto meanQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*meanQueueDescriptor, info); } case LayerType::MemCopy: { auto memCopyQueueDescriptor = PolymorphicDowncast(&descriptor); if (descriptor.m_Inputs.empty()) { throw InvalidArgumentException("RefWorkloadFactory: CreateMemCopy() expected an input tensor."); } return std::make_unique(*memCopyQueueDescriptor, info); } case LayerType::MemImport: { auto memImportQueueDescriptor = PolymorphicDowncast(&descriptor); if (descriptor.m_Inputs.empty()) { throw InvalidArgumentException("RefWorkloadFactory: CreateMemImport() expected an input tensor."); } return std::make_unique(*memImportQueueDescriptor, info); } case LayerType::Minimum: { auto minimumQueueDescriptor = PolymorphicDowncast(&descriptor); if (info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Signed32) { return std::make_unique>(*minimumQueueDescriptor, info); } else { return std::make_unique>(*minimumQueueDescriptor, info); } } case LayerType::Multiplication: { auto multiplicationQueueDescriptor = PolymorphicDowncast(&descriptor); if (info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Signed32) { return std::make_unique>(*multiplicationQueueDescriptor, info); } else { return std::make_unique>(*multiplicationQueueDescriptor, info); } } case LayerType::Normalization: { auto normalizationQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*normalizationQueueDescriptor, info); } case LayerType::Output: { auto outputQueueDescriptor = PolymorphicDowncast(&descriptor); if (info.m_InputTensorInfos.empty() ) { throw InvalidArgumentException("RefWorkloadFactory::CreateOutput: Input cannot be zero length"); } if (info.m_OutputTensorInfos.empty()) { throw InvalidArgumentException("RefWorkloadFactory::CreateOutput: Output cannot be zero length"); } if (info.m_InputTensorInfos[0].GetNumBytes() != info.m_OutputTensorInfos[0].GetNumBytes()) { throw InvalidArgumentException("RefWorkloadFactory::CreateOutput: data input and output " "differ in byte count."); } return std::make_unique(*outputQueueDescriptor, info); } case LayerType::Pad: { auto padQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*padQueueDescriptor, info); } case LayerType::Permute: { auto permuteQueueDescriptor = PolymorphicDowncast(&descriptor); if (IsQSymmS16(info)) { return std::make_unique(*permuteQueueDescriptor, info); } else if (IsBFloat16(info)) { return std::make_unique(*permuteQueueDescriptor, info); } else if (IsQAsymmS8(info)) { return std::make_unique(*permuteQueueDescriptor, info); } return MakeWorkloadHelper(*permuteQueueDescriptor, info); } case LayerType::Pooling2d: { auto pooling2dQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*pooling2dQueueDescriptor, info); } case LayerType::Pooling3d: { auto pooling3dQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*pooling3dQueueDescriptor, info); } case LayerType::PreCompiled: { return nullptr; } case LayerType::Prelu: { auto preluQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*preluQueueDescriptor, info); } case LayerType::QLstm: { auto qlstmQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*qlstmQueueDescriptor, info); } case LayerType::Quantize: { auto quantizeQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*quantizeQueueDescriptor, info); } case LayerType::Rank: { auto rankQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*rankQueueDescriptor, info); } case LayerType::Reduce: { auto reduceQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*reduceQueueDescriptor, info); } case LayerType::Reshape: { auto reshapeQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*reshapeQueueDescriptor, info); } case LayerType::Resize: { auto resizeQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*resizeQueueDescriptor, info); } case LayerType::Shape: { auto shapeQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*shapeQueueDescriptor, info); } case LayerType::Slice: { auto sliceQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*sliceQueueDescriptor, info); } case LayerType::Softmax: { auto softmaxQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*softmaxQueueDescriptor, info); } case LayerType::SpaceToBatchNd: { auto spaceToBatchNdQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*spaceToBatchNdQueueDescriptor, info); } case LayerType::SpaceToDepth: { auto spaceToDepthQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*spaceToDepthQueueDescriptor, info); } case LayerType::Splitter: { auto splitterQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*splitterQueueDescriptor, info); } case LayerType::Stack: { auto stackQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*stackQueueDescriptor, info); } case LayerType::StridedSlice: { auto stridedSliceQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*stridedSliceQueueDescriptor, info); } case LayerType::Subtraction: { auto subtractionQueueDescriptor = PolymorphicDowncast(&descriptor); if (info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Signed32) { return std::make_unique>(*subtractionQueueDescriptor, info); } else { return std::make_unique>(*subtractionQueueDescriptor, info); } } case LayerType::Transpose: { auto transposeQueueDescriptor = PolymorphicDowncast(&descriptor); if (IsQSymmS16(info)) { return std::make_unique(*transposeQueueDescriptor, info); } else if (IsBFloat16(info)) { return std::make_unique(*transposeQueueDescriptor, info); } else if (IsQAsymmS8(info)) { return std::make_unique(*transposeQueueDescriptor, info); } return MakeWorkloadHelper (*transposeQueueDescriptor, info); } case LayerType::TransposeConvolution2d: { auto transposeConvolution2dQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*transposeConvolution2dQueueDescriptor, info); } case LayerType::UnidirectionalSequenceLstm: { auto unidirectionalSequenceLstmQueueDescriptor = PolymorphicDowncast(&descriptor); return std::make_unique(*unidirectionalSequenceLstmQueueDescriptor, info); } default: return nullptr; } } std::unique_ptr RefWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateAddition(const AdditionQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Signed32) { return std::make_unique>(descriptor, info); } else { return std::make_unique>(descriptor, info); } } std::unique_ptr RefWorkloadFactory::CreateArgMinMax(const ArgMinMaxQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateBatchNormalization( const BatchNormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateBatchToSpaceNd(const BatchToSpaceNdQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateCast(const CastQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateChannelShuffle(const ChannelShuffleQueueDescriptor &descriptor, const WorkloadInfo &info) const { return std::make_unique(descriptor,info); } std::unique_ptr RefWorkloadFactory::CreateComparison(const ComparisonQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateConcat(const ConcatQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateConstant(const ConstantQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateConvertBf16ToFp32( const ConvertBf16ToFp32QueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateConvertFp16ToFp32( const ConvertFp16ToFp32QueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateConvertFp32ToBf16( const ConvertFp32ToBf16QueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateConvertFp32ToFp16( const ConvertFp32ToFp16QueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateConvolution2d(const Convolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateConvolution3d(const Convolution3dQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateDebug(const DebugQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (IsBFloat16(info)) { return std::make_unique(descriptor, info); } if (IsFloat16(info)) { return std::make_unique(descriptor, info); } if (IsQSymmS16(info)) { return std::make_unique(descriptor, info); } if (IsQSymmS8(info)) { return std::make_unique(descriptor, info); } if (IsQAsymmU8(info)) { return std::make_unique(descriptor, info); } if (IsQAsymmS8(info)) { return std::make_unique(descriptor, info); } if (IsSigned32(info)) { return std::make_unique(descriptor, info); } return MakeWorkload(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateDepthToSpace(const DepthToSpaceQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateDepthwiseConvolution2d( const DepthwiseConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateDequantize(const DequantizeQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateDetectionPostProcess( const DetectionPostProcessQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateDivision(const DivisionQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Signed32) { return std::make_unique>(descriptor, info); } else { return std::make_unique>(descriptor, info); } } std::unique_ptr RefWorkloadFactory::CreateElementwiseUnary(const ElementwiseUnaryQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (descriptor.m_Parameters.m_Operation == UnaryOperation::LogicalNot) { return std::make_unique(descriptor, info); } return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateFakeQuantization(const FakeQuantizationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return MakeWorkload(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateFill(const FillQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateFloor(const FloorQueueDescriptor& descriptor, const WorkloadInfo& info) const { if(IsQuantizedType(info.m_InputTensorInfos[0].GetDataType())) { return nullptr; } else { return std::make_unique(descriptor, info); } } std::unique_ptr RefWorkloadFactory::CreateFullyConnected( const FullyConnectedQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateGather(const GatherQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateInput(const InputQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (info.m_InputTensorInfos.empty() ) { throw InvalidArgumentException("RefWorkloadFactory::CreateInput: Input cannot be zero length"); } if (info.m_OutputTensorInfos.empty()) { throw InvalidArgumentException("RefWorkloadFactory::CreateInput: Output cannot be zero length"); } if (info.m_InputTensorInfos[0].GetNumBytes() != info.m_OutputTensorInfos[0].GetNumBytes()) { throw InvalidArgumentException("RefWorkloadFactory::CreateInput: data input and output differ in byte count."); } return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateInstanceNormalization( const InstanceNormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateL2Normalization(const L2NormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateLogicalBinary(const LogicalBinaryQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateLogSoftmax(const LogSoftmaxQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateLstm(const LstmQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateMaximum(const MaximumQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Signed32) { return std::make_unique>(descriptor, info); } else { return std::make_unique>(descriptor, info); } } std::unique_ptr RefWorkloadFactory::CreateMean(const MeanQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateMemCopy(const MemCopyQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (descriptor.m_Inputs.empty()) { throw InvalidArgumentException("RefWorkloadFactory: CreateMemCopy() expected an input tensor."); } return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateMemImport(const MemImportQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (descriptor.m_Inputs.empty()) { throw InvalidArgumentException("RefWorkloadFactory: CreateMemImport() expected an input tensor."); } return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateMinimum(const MinimumQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Signed32) { return std::make_unique>(descriptor, info); } else { return std::make_unique>(descriptor, info); } } std::unique_ptr RefWorkloadFactory::CreateMultiplication(const MultiplicationQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Signed32) { return std::make_unique>(descriptor, info); } else { return std::make_unique>(descriptor, info); } } std::unique_ptr RefWorkloadFactory::CreateNormalization(const NormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateOutput(const OutputQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (info.m_InputTensorInfos.empty() ) { throw InvalidArgumentException("RefWorkloadFactory::CreateOutput: Input cannot be zero length"); } if (info.m_OutputTensorInfos.empty()) { throw InvalidArgumentException("RefWorkloadFactory::CreateOutput: Output cannot be zero length"); } if (info.m_InputTensorInfos[0].GetNumBytes() != info.m_OutputTensorInfos[0].GetNumBytes()) { throw InvalidArgumentException("RefWorkloadFactory::CreateOutput: data input and output differ in byte count."); } return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreatePad(const PadQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreatePermute(const PermuteQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (IsQSymmS16(info)) { return std::make_unique(descriptor, info); } else if (IsBFloat16(info)) { return std::make_unique(descriptor, info); } else if (IsQAsymmS8(info)) { return std::make_unique(descriptor, info); } return MakeWorkloadHelper(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreatePooling2d(const Pooling2dQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreatePooling3d(const Pooling3dQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreatePreCompiled(const PreCompiledQueueDescriptor& /*descriptor*/, const WorkloadInfo& /*info*/) const { return nullptr; } std::unique_ptr RefWorkloadFactory::CreatePrelu(const PreluQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateQLstm(const QLstmQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateQuantize(const QuantizeQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateRank(const RankQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateReduce(const ReduceQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateReshape(const ReshapeQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateResize(const ResizeQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateShape(const ShapeQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateSlice(const SliceQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateSoftmax(const SoftmaxQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateSpaceToBatchNd(const SpaceToBatchNdQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateSpaceToDepth(const SpaceToDepthQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateSplitter(const SplitterQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateStack(const StackQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateStridedSlice(const StridedSliceQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateSubtraction(const SubtractionQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Signed32) { return std::make_unique>(descriptor, info); } else { return std::make_unique>(descriptor, info); } } std::unique_ptr RefWorkloadFactory::CreateTranspose(const TransposeQueueDescriptor& descriptor, const WorkloadInfo& info) const { if (IsQSymmS16(info)) { return std::make_unique(descriptor, info); } else if (IsBFloat16(info)) { return std::make_unique(descriptor, info); } else if (IsQAsymmS8(info)) { return std::make_unique(descriptor, info); } return MakeWorkloadHelper(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateTransposeConvolution2d( const TransposeConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateUnidirectionalSequenceLstm( const UnidirectionalSequenceLstmQueueDescriptor& descriptor, const WorkloadInfo& info) const { return std::make_unique(descriptor, info);; } } // namespace armnn