IVGCVSW-5327 Add to Layer a binary blob to host the activation layer info
Signed-off-by: Keith Davis <keith.davis@arm.com>
Change-Id: I0a07dea96a86849701ba387dbea148909a6d729b
diff --git a/src/armnn/Layer.cpp b/src/armnn/Layer.cpp
index d06b045..62f861b 100644
--- a/src/armnn/Layer.cpp
+++ b/src/armnn/Layer.cpp
@@ -242,6 +242,11 @@
}
}
+void Layer::SetAdditionalInfo(QueueDescriptor& descriptor) const
+{
+ descriptor.m_AdditionalInfoObject = m_AdditionalInfoObject.get();
+}
+
void Layer::CreateTensorHandles(const TensorHandleFactoryRegistry& registry,
const IWorkloadFactory& workloadFactory,
const bool IsMemoryManaged)
diff --git a/src/armnn/Layer.hpp b/src/armnn/Layer.hpp
index fff5773..6cb3b8f 100644
--- a/src/armnn/Layer.hpp
+++ b/src/armnn/Layer.hpp
@@ -28,6 +28,7 @@
#include <memory>
#include <string>
#include <vector>
+#include <backendsCommon/WorkloadData.hpp>
namespace armnn
{
@@ -204,6 +205,7 @@
// Base layer class
using LayerPriority = unsigned int;
+using AdditionalInfoObjectPtr = std::shared_ptr<void>;
class Layer : public IConnectableLayer
{
@@ -333,6 +335,17 @@
m_ShapeInferenceMethod = shapeInferenceMethod;
}
+ template<typename T>
+ std::shared_ptr<T> GetAdditionalInformation()
+ {
+ return std::static_pointer_cast<T>(m_AdditionalInfoObject);
+ }
+
+ void SetAdditionalInfoForObject(const AdditionalInfoObjectPtr& additionalInfo)
+ {
+ m_AdditionalInfoObject = additionalInfo;
+ }
+
protected:
// Graph needs access to the virtual destructor.
friend class Graph;
@@ -377,6 +390,12 @@
using ConstantTensors = std::vector<std::reference_wrapper<std::unique_ptr<ScopedCpuTensorHandle>>>;
virtual ConstantTensors GetConstantTensorsByRef() {return ConstantTensors(); };
+ // "Blob"
+ AdditionalInfoObjectPtr m_AdditionalInfoObject;
+
+ // Utility method to set a pointer in the queueDescriptor to the "blob" location in the layer
+ void SetAdditionalInfo(QueueDescriptor& descriptor) const;
+
private:
void CollectWorkloadInputs(WorkloadDataCollector& dataCollector) const;
void CollectWorkloadOutputs(WorkloadDataCollector& dataCollector) const;
diff --git a/src/armnn/layers/AbsLayer.cpp b/src/armnn/layers/AbsLayer.cpp
index e04fcbb..7aa4099 100644
--- a/src/armnn/layers/AbsLayer.cpp
+++ b/src/armnn/layers/AbsLayer.cpp
@@ -22,6 +22,8 @@
std::unique_ptr<IWorkload> AbsLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
AbsQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateAbs(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/ActivationLayer.cpp b/src/armnn/layers/ActivationLayer.cpp
index d3d02c3..7bfa28e 100644
--- a/src/armnn/layers/ActivationLayer.cpp
+++ b/src/armnn/layers/ActivationLayer.cpp
@@ -20,6 +20,8 @@
std::unique_ptr<IWorkload> ActivationLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
ActivationQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateActivation(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/AdditionLayer.cpp b/src/armnn/layers/AdditionLayer.cpp
index b27f450..8b1f2a8 100644
--- a/src/armnn/layers/AdditionLayer.cpp
+++ b/src/armnn/layers/AdditionLayer.cpp
@@ -22,6 +22,8 @@
std::unique_ptr<IWorkload> AdditionLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
AdditionQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateAddition(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/ArgMinMaxLayer.cpp b/src/armnn/layers/ArgMinMaxLayer.cpp
index bd914ec..219f346 100644
--- a/src/armnn/layers/ArgMinMaxLayer.cpp
+++ b/src/armnn/layers/ArgMinMaxLayer.cpp
@@ -24,6 +24,8 @@
std::unique_ptr<IWorkload> ArgMinMaxLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
ArgMinMaxQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateArgMinMax(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/BatchNormalizationLayer.cpp b/src/armnn/layers/BatchNormalizationLayer.cpp
index 625e0d4..ce351a4 100644
--- a/src/armnn/layers/BatchNormalizationLayer.cpp
+++ b/src/armnn/layers/BatchNormalizationLayer.cpp
@@ -27,6 +27,7 @@
ARMNN_ASSERT_MSG(m_Gamma != nullptr, "BatchNormalizationLayer: Gamma data should not be null.");
BatchNormalizationQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
descriptor.m_Mean = m_Mean.get();
descriptor.m_Variance = m_Variance.get();
diff --git a/src/armnn/layers/BatchToSpaceNdLayer.cpp b/src/armnn/layers/BatchToSpaceNdLayer.cpp
index 1a5cfa6..a13b0b7 100644
--- a/src/armnn/layers/BatchToSpaceNdLayer.cpp
+++ b/src/armnn/layers/BatchToSpaceNdLayer.cpp
@@ -31,6 +31,7 @@
std::unique_ptr<IWorkload> BatchToSpaceNdLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
BatchToSpaceNdQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
return factory.CreateBatchToSpaceNd(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/ComparisonLayer.cpp b/src/armnn/layers/ComparisonLayer.cpp
index a9639e8..399834d 100644
--- a/src/armnn/layers/ComparisonLayer.cpp
+++ b/src/armnn/layers/ComparisonLayer.cpp
@@ -23,6 +23,8 @@
std::unique_ptr<IWorkload> ComparisonLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
ComparisonQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateComparison(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/ConcatLayer.cpp b/src/armnn/layers/ConcatLayer.cpp
index affbe71..238fdb6 100644
--- a/src/armnn/layers/ConcatLayer.cpp
+++ b/src/armnn/layers/ConcatLayer.cpp
@@ -31,6 +31,7 @@
descriptor.m_ViewOrigins.emplace_back(
std::vector<unsigned int>(m_Param.GetViewOrigin(i), m_Param.GetViewOrigin(i) + m_Param.GetNumDimensions()));
}
+ SetAdditionalInfo(descriptor);
return factory.CreateConcat(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/ConstantLayer.cpp b/src/armnn/layers/ConstantLayer.cpp
index cd8a056..76b9997 100644
--- a/src/armnn/layers/ConstantLayer.cpp
+++ b/src/armnn/layers/ConstantLayer.cpp
@@ -22,6 +22,8 @@
{
ConstantQueueDescriptor descriptor;
descriptor.m_LayerOutput = m_LayerOutput.get();
+ SetAdditionalInfo(descriptor);
+
return factory.CreateConstant(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/ConvertBf16ToFp32Layer.cpp b/src/armnn/layers/ConvertBf16ToFp32Layer.cpp
index 81bb4d9..3577723 100644
--- a/src/armnn/layers/ConvertBf16ToFp32Layer.cpp
+++ b/src/armnn/layers/ConvertBf16ToFp32Layer.cpp
@@ -22,6 +22,8 @@
std::unique_ptr<IWorkload> ConvertBf16ToFp32Layer::CreateWorkload(const IWorkloadFactory& factory) const
{
ConvertBf16ToFp32QueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateConvertBf16ToFp32(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/ConvertFp16ToFp32Layer.cpp b/src/armnn/layers/ConvertFp16ToFp32Layer.cpp
index 709ca13..3b6f72c 100644
--- a/src/armnn/layers/ConvertFp16ToFp32Layer.cpp
+++ b/src/armnn/layers/ConvertFp16ToFp32Layer.cpp
@@ -22,6 +22,8 @@
std::unique_ptr<IWorkload> ConvertFp16ToFp32Layer::CreateWorkload(const IWorkloadFactory& factory) const
{
ConvertFp16ToFp32QueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateConvertFp16ToFp32(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/ConvertFp32ToBf16Layer.cpp b/src/armnn/layers/ConvertFp32ToBf16Layer.cpp
index 9b02b2f..f909769 100644
--- a/src/armnn/layers/ConvertFp32ToBf16Layer.cpp
+++ b/src/armnn/layers/ConvertFp32ToBf16Layer.cpp
@@ -22,6 +22,8 @@
std::unique_ptr<IWorkload> ConvertFp32ToBf16Layer::CreateWorkload(const IWorkloadFactory& factory) const
{
ConvertFp32ToBf16QueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateConvertFp32ToBf16(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/ConvertFp32ToFp16Layer.cpp b/src/armnn/layers/ConvertFp32ToFp16Layer.cpp
index 7b2df00..3e6f055 100644
--- a/src/armnn/layers/ConvertFp32ToFp16Layer.cpp
+++ b/src/armnn/layers/ConvertFp32ToFp16Layer.cpp
@@ -21,6 +21,8 @@
std::unique_ptr<IWorkload> ConvertFp32ToFp16Layer::CreateWorkload(const IWorkloadFactory& factory) const
{
ConvertFp32ToFp16QueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateConvertFp32ToFp16(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/Convolution2dLayer.cpp b/src/armnn/layers/Convolution2dLayer.cpp
index 5fff982..26f11f3 100644
--- a/src/armnn/layers/Convolution2dLayer.cpp
+++ b/src/armnn/layers/Convolution2dLayer.cpp
@@ -60,6 +60,9 @@
ARMNN_ASSERT_MSG(m_Bias != nullptr, "Convolution2dLayer: Bias data should not be null.");
descriptor.m_Bias = m_Bias.get();
}
+
+ SetAdditionalInfo(descriptor);
+
return factory.CreateConvolution2d(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/DebugLayer.cpp b/src/armnn/layers/DebugLayer.cpp
index c29421f..ade09ed 100644
--- a/src/armnn/layers/DebugLayer.cpp
+++ b/src/armnn/layers/DebugLayer.cpp
@@ -26,6 +26,8 @@
descriptor.m_LayerName = prevLayer.GetNameStr();
descriptor.m_SlotIndex = GetInputSlot(0).GetConnectedOutputSlot()->CalculateIndexOnOwner();
+ SetAdditionalInfo(descriptor);
+
return factory.CreateDebug(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/DepthToSpaceLayer.cpp b/src/armnn/layers/DepthToSpaceLayer.cpp
index dae557e..dfa575b 100644
--- a/src/armnn/layers/DepthToSpaceLayer.cpp
+++ b/src/armnn/layers/DepthToSpaceLayer.cpp
@@ -28,6 +28,8 @@
descriptor.m_Parameters.m_BlockSize = m_Param.m_BlockSize;
descriptor.m_Parameters.m_DataLayout = m_Param.m_DataLayout;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateDepthToSpace(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/DepthwiseConvolution2dLayer.cpp b/src/armnn/layers/DepthwiseConvolution2dLayer.cpp
index 8a7cf23..139d268 100644
--- a/src/armnn/layers/DepthwiseConvolution2dLayer.cpp
+++ b/src/armnn/layers/DepthwiseConvolution2dLayer.cpp
@@ -62,6 +62,9 @@
ARMNN_ASSERT_MSG(m_Bias != nullptr, "DepthwiseConvolution2dLayer: Bias data should not be null.");
descriptor.m_Bias = m_Bias.get();
}
+
+ SetAdditionalInfo(descriptor);
+
return factory.CreateDepthwiseConvolution2d(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/DequantizeLayer.cpp b/src/armnn/layers/DequantizeLayer.cpp
index f798882..cbe9ae1 100644
--- a/src/armnn/layers/DequantizeLayer.cpp
+++ b/src/armnn/layers/DequantizeLayer.cpp
@@ -20,6 +20,7 @@
const IWorkloadFactory& factory) const
{
DequantizeQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
return factory.CreateDequantize(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/DetectionPostProcessLayer.cpp b/src/armnn/layers/DetectionPostProcessLayer.cpp
index b18781b..d54bf26 100644
--- a/src/armnn/layers/DetectionPostProcessLayer.cpp
+++ b/src/armnn/layers/DetectionPostProcessLayer.cpp
@@ -24,6 +24,8 @@
{
DetectionPostProcessQueueDescriptor descriptor;
descriptor.m_Anchors = m_Anchors.get();
+ SetAdditionalInfo(descriptor);
+
return factory.CreateDetectionPostProcess(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/DivisionLayer.cpp b/src/armnn/layers/DivisionLayer.cpp
index 193b96b..5b032ce 100644
--- a/src/armnn/layers/DivisionLayer.cpp
+++ b/src/armnn/layers/DivisionLayer.cpp
@@ -22,6 +22,8 @@
std::unique_ptr<IWorkload> DivisionLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
DivisionQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateDivision(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/ElementwiseUnaryLayer.cpp b/src/armnn/layers/ElementwiseUnaryLayer.cpp
index cf4c2fc..74fa16e 100644
--- a/src/armnn/layers/ElementwiseUnaryLayer.cpp
+++ b/src/armnn/layers/ElementwiseUnaryLayer.cpp
@@ -23,6 +23,7 @@
std::unique_ptr<IWorkload> ElementwiseUnaryLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
ElementwiseUnaryQueueDescriptor descriptor;
+
return factory.CreateElementwiseUnary(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/FakeQuantizationLayer.cpp b/src/armnn/layers/FakeQuantizationLayer.cpp
index ab41324..a316b2b 100644
--- a/src/armnn/layers/FakeQuantizationLayer.cpp
+++ b/src/armnn/layers/FakeQuantizationLayer.cpp
@@ -21,6 +21,8 @@
std::unique_ptr<IWorkload> FakeQuantizationLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
FakeQuantizationQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateFakeQuantization(descriptor, PrepInfoAndDesc(descriptor) );
}
diff --git a/src/armnn/layers/FillLayer.cpp b/src/armnn/layers/FillLayer.cpp
index 329a30a..41471c3 100644
--- a/src/armnn/layers/FillLayer.cpp
+++ b/src/armnn/layers/FillLayer.cpp
@@ -21,6 +21,8 @@
std::unique_ptr<IWorkload> FillLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
FillQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateFill(descriptor, PrepInfoAndDesc(descriptor) );
}
diff --git a/src/armnn/layers/FloorLayer.cpp b/src/armnn/layers/FloorLayer.cpp
index 5ff9a9a..e03bdb1 100644
--- a/src/armnn/layers/FloorLayer.cpp
+++ b/src/armnn/layers/FloorLayer.cpp
@@ -21,6 +21,8 @@
std::unique_ptr<IWorkload> FloorLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
FloorQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateFloor(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/FullyConnectedLayer.cpp b/src/armnn/layers/FullyConnectedLayer.cpp
index f10beda..0dc138b 100644
--- a/src/armnn/layers/FullyConnectedLayer.cpp
+++ b/src/armnn/layers/FullyConnectedLayer.cpp
@@ -26,12 +26,16 @@
FullyConnectedQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
descriptor.m_Weight = m_Weight.get();
if (m_Param.m_BiasEnabled)
{
ARMNN_ASSERT_MSG(m_Bias != nullptr, "FullyConnectedLayer: Bias data should not be null.");
descriptor.m_Bias = m_Bias.get();
}
+
+ SetAdditionalInfo(descriptor);
+
return factory.CreateFullyConnected(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/GatherLayer.cpp b/src/armnn/layers/GatherLayer.cpp
index e5d4a18..9a4f9bf 100644
--- a/src/armnn/layers/GatherLayer.cpp
+++ b/src/armnn/layers/GatherLayer.cpp
@@ -21,6 +21,8 @@
std::unique_ptr<IWorkload> GatherLayer::CreateWorkload(const armnn::IWorkloadFactory& factory) const
{
GatherQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateGather(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/InstanceNormalizationLayer.cpp b/src/armnn/layers/InstanceNormalizationLayer.cpp
index eb6fe90..87c6877 100644
--- a/src/armnn/layers/InstanceNormalizationLayer.cpp
+++ b/src/armnn/layers/InstanceNormalizationLayer.cpp
@@ -21,6 +21,8 @@
std::unique_ptr<IWorkload> InstanceNormalizationLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
InstanceNormalizationQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateInstanceNormalization(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/L2NormalizationLayer.cpp b/src/armnn/layers/L2NormalizationLayer.cpp
index ab2b094..c96e708 100644
--- a/src/armnn/layers/L2NormalizationLayer.cpp
+++ b/src/armnn/layers/L2NormalizationLayer.cpp
@@ -21,6 +21,8 @@
std::unique_ptr<IWorkload> L2NormalizationLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
L2NormalizationQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateL2Normalization(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/LogSoftmaxLayer.cpp b/src/armnn/layers/LogSoftmaxLayer.cpp
index 1620acb..24e79ce 100644
--- a/src/armnn/layers/LogSoftmaxLayer.cpp
+++ b/src/armnn/layers/LogSoftmaxLayer.cpp
@@ -21,6 +21,8 @@
std::unique_ptr<IWorkload> LogSoftmaxLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
LogSoftmaxQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateLogSoftmax(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/LstmLayer.cpp b/src/armnn/layers/LstmLayer.cpp
index 724bd6b..8e396ab 100644
--- a/src/armnn/layers/LstmLayer.cpp
+++ b/src/armnn/layers/LstmLayer.cpp
@@ -72,6 +72,8 @@
descriptor.m_OutputLayerNormWeights = m_LayerNormParameters.m_OutputLayerNormWeights.get();
}
+ SetAdditionalInfo(descriptor);
+
return factory.CreateLstm(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/MapLayer.cpp b/src/armnn/layers/MapLayer.cpp
index bc6cbf1..608a71e 100644
--- a/src/armnn/layers/MapLayer.cpp
+++ b/src/armnn/layers/MapLayer.cpp
@@ -28,6 +28,7 @@
{
IgnoreUnused(factory);
MapQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
//This is different from other workloads. Does not get created by the workload factory.
return std::make_unique<MapWorkload>(descriptor, PrepInfoAndDesc(descriptor));
diff --git a/src/armnn/layers/MaximumLayer.cpp b/src/armnn/layers/MaximumLayer.cpp
index ab7bf88..d57e9e6 100644
--- a/src/armnn/layers/MaximumLayer.cpp
+++ b/src/armnn/layers/MaximumLayer.cpp
@@ -21,6 +21,8 @@
std::unique_ptr<IWorkload> MaximumLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
MaximumQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateMaximum(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/MeanLayer.cpp b/src/armnn/layers/MeanLayer.cpp
index 0c5959c..b5c7708 100644
--- a/src/armnn/layers/MeanLayer.cpp
+++ b/src/armnn/layers/MeanLayer.cpp
@@ -26,6 +26,7 @@
MeanQueueDescriptor descriptor;
descriptor.m_Parameters.m_Axis = m_Param.m_Axis;
descriptor.m_Parameters.m_KeepDims = m_Param.m_KeepDims;
+ SetAdditionalInfo(descriptor);
return factory.CreateMean(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/MemCopyLayer.cpp b/src/armnn/layers/MemCopyLayer.cpp
index 854b4f6..d9a802c 100644
--- a/src/armnn/layers/MemCopyLayer.cpp
+++ b/src/armnn/layers/MemCopyLayer.cpp
@@ -28,6 +28,7 @@
{
IgnoreUnused(factory);
MemCopyQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
//This is different from other workloads. Does not get created by the workload factory.
return std::make_unique<CopyMemGenericWorkload>(descriptor, PrepInfoAndDesc(descriptor));
diff --git a/src/armnn/layers/MemImportLayer.cpp b/src/armnn/layers/MemImportLayer.cpp
index d9148fb..3d1c702 100644
--- a/src/armnn/layers/MemImportLayer.cpp
+++ b/src/armnn/layers/MemImportLayer.cpp
@@ -28,6 +28,7 @@
{
IgnoreUnused(factory);
MemImportQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
//This is different from other workloads. Does not get created by the workload factory.
return std::make_unique<ImportMemGenericWorkload>(descriptor, PrepInfoAndDesc(descriptor));
diff --git a/src/armnn/layers/MinimumLayer.cpp b/src/armnn/layers/MinimumLayer.cpp
index 9154d78..f60815e 100644
--- a/src/armnn/layers/MinimumLayer.cpp
+++ b/src/armnn/layers/MinimumLayer.cpp
@@ -22,6 +22,8 @@
std::unique_ptr<IWorkload> MinimumLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
MinimumQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateMinimum(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/MultiplicationLayer.cpp b/src/armnn/layers/MultiplicationLayer.cpp
index f02ee57..8fc13ac 100644
--- a/src/armnn/layers/MultiplicationLayer.cpp
+++ b/src/armnn/layers/MultiplicationLayer.cpp
@@ -22,6 +22,8 @@
std::unique_ptr<IWorkload> MultiplicationLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
MultiplicationQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateMultiplication(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/NormalizationLayer.cpp b/src/armnn/layers/NormalizationLayer.cpp
index b75bb33..4bf97ed 100644
--- a/src/armnn/layers/NormalizationLayer.cpp
+++ b/src/armnn/layers/NormalizationLayer.cpp
@@ -21,6 +21,8 @@
std::unique_ptr<IWorkload> NormalizationLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
NormalizationQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateNormalization(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/PadLayer.cpp b/src/armnn/layers/PadLayer.cpp
index a8c749c..324dd4a 100644
--- a/src/armnn/layers/PadLayer.cpp
+++ b/src/armnn/layers/PadLayer.cpp
@@ -23,6 +23,7 @@
{
PadQueueDescriptor descriptor;
descriptor.m_Parameters.m_PadList = m_Param.m_PadList;
+ SetAdditionalInfo(descriptor);
return factory.CreatePad(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/PermuteLayer.cpp b/src/armnn/layers/PermuteLayer.cpp
index 3c4d1ee..859e687 100644
--- a/src/armnn/layers/PermuteLayer.cpp
+++ b/src/armnn/layers/PermuteLayer.cpp
@@ -25,6 +25,8 @@
std::unique_ptr<IWorkload> PermuteLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
PermuteQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreatePermute(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/Pooling2dLayer.cpp b/src/armnn/layers/Pooling2dLayer.cpp
index 5411695..dbeee84 100644
--- a/src/armnn/layers/Pooling2dLayer.cpp
+++ b/src/armnn/layers/Pooling2dLayer.cpp
@@ -27,6 +27,8 @@
std::unique_ptr<IWorkload> Pooling2dLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
Pooling2dQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreatePooling2d(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/PreCompiledLayer.cpp b/src/armnn/layers/PreCompiledLayer.cpp
index afc9877..dbbc1fd 100644
--- a/src/armnn/layers/PreCompiledLayer.cpp
+++ b/src/armnn/layers/PreCompiledLayer.cpp
@@ -32,6 +32,8 @@
{
PreCompiledQueueDescriptor descriptor;
descriptor.m_PreCompiledObject = m_PreCompiledObject.get();
+ SetAdditionalInfo(descriptor);
+
return factory.CreatePreCompiled(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/PreluLayer.cpp b/src/armnn/layers/PreluLayer.cpp
index 365dd4f..f9f534e 100644
--- a/src/armnn/layers/PreluLayer.cpp
+++ b/src/armnn/layers/PreluLayer.cpp
@@ -23,6 +23,7 @@
std::unique_ptr<IWorkload> PreluLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
PreluQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
return factory.CreatePrelu(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/QLstmLayer.cpp b/src/armnn/layers/QLstmLayer.cpp
index 4d0d57c..85f99bd 100644
--- a/src/armnn/layers/QLstmLayer.cpp
+++ b/src/armnn/layers/QLstmLayer.cpp
@@ -73,6 +73,8 @@
descriptor.m_OutputLayerNormWeights = m_LayerNormParameters.m_OutputLayerNormWeights.get();
}
+ SetAdditionalInfo(descriptor);
+
return factory.CreateQLstm(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/QuantizeLayer.cpp b/src/armnn/layers/QuantizeLayer.cpp
index aad6dd8..6ce28c41 100644
--- a/src/armnn/layers/QuantizeLayer.cpp
+++ b/src/armnn/layers/QuantizeLayer.cpp
@@ -19,7 +19,10 @@
std::unique_ptr<IWorkload> QuantizeLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
QuantizeQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
WorkloadInfo info = PrepInfoAndDesc(descriptor);
+
return factory.CreateQuantize(descriptor, info);
}
diff --git a/src/armnn/layers/QuantizedLstmLayer.cpp b/src/armnn/layers/QuantizedLstmLayer.cpp
index ad22761..624e443 100644
--- a/src/armnn/layers/QuantizedLstmLayer.cpp
+++ b/src/armnn/layers/QuantizedLstmLayer.cpp
@@ -39,6 +39,8 @@
descriptor.m_CellBias = m_QuantizedLstmParameters.m_CellBias.get();
descriptor.m_OutputGateBias = m_QuantizedLstmParameters.m_OutputGateBias.get();
+ SetAdditionalInfo(descriptor);
+
return factory.CreateQuantizedLstm(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/RankLayer.cpp b/src/armnn/layers/RankLayer.cpp
index 2e70134..2b0dffe 100644
--- a/src/armnn/layers/RankLayer.cpp
+++ b/src/armnn/layers/RankLayer.cpp
@@ -20,6 +20,8 @@
std::unique_ptr<IWorkload> RankLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
RankQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateRank(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/ReshapeLayer.cpp b/src/armnn/layers/ReshapeLayer.cpp
index 5265316..f303ff7 100644
--- a/src/armnn/layers/ReshapeLayer.cpp
+++ b/src/armnn/layers/ReshapeLayer.cpp
@@ -22,6 +22,8 @@
std::unique_ptr<IWorkload> ReshapeLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
ReshapeQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateReshape(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/ResizeLayer.cpp b/src/armnn/layers/ResizeLayer.cpp
index 53af5f9..3a390d4 100644
--- a/src/armnn/layers/ResizeLayer.cpp
+++ b/src/armnn/layers/ResizeLayer.cpp
@@ -26,6 +26,8 @@
std::unique_ptr<IWorkload> ResizeLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
ResizeQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateResize(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/RsqrtLayer.cpp b/src/armnn/layers/RsqrtLayer.cpp
index e85d865..9c09701 100644
--- a/src/armnn/layers/RsqrtLayer.cpp
+++ b/src/armnn/layers/RsqrtLayer.cpp
@@ -22,6 +22,8 @@
std::unique_ptr<IWorkload> RsqrtLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
RsqrtQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateRsqrt(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/SliceLayer.cpp b/src/armnn/layers/SliceLayer.cpp
index bfa16e5..b512ca4 100644
--- a/src/armnn/layers/SliceLayer.cpp
+++ b/src/armnn/layers/SliceLayer.cpp
@@ -24,6 +24,8 @@
std::unique_ptr<IWorkload> SliceLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
SliceQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateSlice(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/SoftmaxLayer.cpp b/src/armnn/layers/SoftmaxLayer.cpp
index 32d3a11..9882da4 100644
--- a/src/armnn/layers/SoftmaxLayer.cpp
+++ b/src/armnn/layers/SoftmaxLayer.cpp
@@ -21,6 +21,8 @@
std::unique_ptr<IWorkload> SoftmaxLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
SoftmaxQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateSoftmax(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/SpaceToBatchNdLayer.cpp b/src/armnn/layers/SpaceToBatchNdLayer.cpp
index decb6e6..b9e3331 100644
--- a/src/armnn/layers/SpaceToBatchNdLayer.cpp
+++ b/src/armnn/layers/SpaceToBatchNdLayer.cpp
@@ -26,9 +26,10 @@
std::unique_ptr<IWorkload> SpaceToBatchNdLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
- SpaceToBatchNdQueueDescriptor descriptor;
+ SpaceToBatchNdQueueDescriptor descriptor;
descriptor.m_Parameters.m_BlockShape = m_Param.m_BlockShape;
- descriptor.m_Parameters.m_PadList = m_Param.m_PadList;
+ descriptor.m_Parameters.m_PadList = m_Param.m_PadList;
+ SetAdditionalInfo(descriptor);
return factory.CreateSpaceToBatchNd(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/SpaceToDepthLayer.cpp b/src/armnn/layers/SpaceToDepthLayer.cpp
index 72d8230..90ba8fc 100644
--- a/src/armnn/layers/SpaceToDepthLayer.cpp
+++ b/src/armnn/layers/SpaceToDepthLayer.cpp
@@ -30,6 +30,8 @@
descriptor.m_Parameters.m_BlockSize = m_Param.m_BlockSize;
descriptor.m_Parameters.m_DataLayout = m_Param.m_DataLayout;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateSpaceToDepth(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/SplitterLayer.cpp b/src/armnn/layers/SplitterLayer.cpp
index e5c9903..5e6622e 100644
--- a/src/armnn/layers/SplitterLayer.cpp
+++ b/src/armnn/layers/SplitterLayer.cpp
@@ -29,6 +29,8 @@
std::vector<unsigned int>(m_Param.GetViewOrigin(i), m_Param.GetViewOrigin(i) + m_Param.GetNumDimensions()));
}
+ SetAdditionalInfo(descriptor);
+
return factory.CreateSplitter(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/StackLayer.cpp b/src/armnn/layers/StackLayer.cpp
index 7150576..11935a1 100644
--- a/src/armnn/layers/StackLayer.cpp
+++ b/src/armnn/layers/StackLayer.cpp
@@ -22,6 +22,8 @@
std::unique_ptr<IWorkload> StackLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
StackQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateStack(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/StridedSliceLayer.cpp b/src/armnn/layers/StridedSliceLayer.cpp
index 957f585..c8f3635 100644
--- a/src/armnn/layers/StridedSliceLayer.cpp
+++ b/src/armnn/layers/StridedSliceLayer.cpp
@@ -34,6 +34,8 @@
descriptor.m_Parameters.m_NewAxisMask = m_Param.m_NewAxisMask;
descriptor.m_Parameters.m_ShrinkAxisMask = m_Param.m_ShrinkAxisMask;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateStridedSlice(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/SubtractionLayer.cpp b/src/armnn/layers/SubtractionLayer.cpp
index 82c9642..34087bd 100644
--- a/src/armnn/layers/SubtractionLayer.cpp
+++ b/src/armnn/layers/SubtractionLayer.cpp
@@ -22,6 +22,8 @@
std::unique_ptr<IWorkload> SubtractionLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
SubtractionQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateSubtraction(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/SwitchLayer.cpp b/src/armnn/layers/SwitchLayer.cpp
index d905f52..8792639 100644
--- a/src/armnn/layers/SwitchLayer.cpp
+++ b/src/armnn/layers/SwitchLayer.cpp
@@ -19,6 +19,8 @@
std::unique_ptr<IWorkload> SwitchLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
SwitchQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateSwitch(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/TransposeConvolution2dLayer.cpp b/src/armnn/layers/TransposeConvolution2dLayer.cpp
index 9287389..1591213 100644
--- a/src/armnn/layers/TransposeConvolution2dLayer.cpp
+++ b/src/armnn/layers/TransposeConvolution2dLayer.cpp
@@ -35,6 +35,8 @@
descriptor.m_Bias = m_Bias.get();
}
+ SetAdditionalInfo(descriptor);
+
return factory.CreateTransposeConvolution2d(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/TransposeLayer.cpp b/src/armnn/layers/TransposeLayer.cpp
index 61e6863..8951fe4 100644
--- a/src/armnn/layers/TransposeLayer.cpp
+++ b/src/armnn/layers/TransposeLayer.cpp
@@ -25,6 +25,8 @@
std::unique_ptr<IWorkload> TransposeLayer::CreateWorkload(const IWorkloadFactory& factory) const
{
TransposeQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
+
return factory.CreateTranspose(descriptor, PrepInfoAndDesc(descriptor));
}
diff --git a/src/armnn/layers/UnmapLayer.cpp b/src/armnn/layers/UnmapLayer.cpp
index d2df9c1..4a43f9f 100644
--- a/src/armnn/layers/UnmapLayer.cpp
+++ b/src/armnn/layers/UnmapLayer.cpp
@@ -28,6 +28,7 @@
{
IgnoreUnused(factory);
UnmapQueueDescriptor descriptor;
+ SetAdditionalInfo(descriptor);
//This is different from other workloads. Does not get created by the workload factory.
return std::make_unique<UnmapWorkload>(descriptor, PrepInfoAndDesc(descriptor));
diff --git a/src/armnn/test/CreateWorkload.hpp b/src/armnn/test/CreateWorkload.hpp
index 60beb51..c07bf6a 100644
--- a/src/armnn/test/CreateWorkload.hpp
+++ b/src/armnn/test/CreateWorkload.hpp
@@ -133,7 +133,177 @@
return workload;
}
-template <typename WorkloadType,
+template<typename WorkloadType,
+ typename DescriptorType,
+ armnn::DataType DataType>
+std::unique_ptr<WorkloadType> CreateSubtractionWithBlobWorkloadTest(armnn::IWorkloadFactory& factory,
+ armnn::Graph& graph)
+{
+ // Creates the layer we're testing.
+ SubtractionLayer* const layer = graph.AddLayer<SubtractionLayer>("layer");
+
+ auto activationDesc = std::make_shared<ActivationDescriptor>();
+ activationDesc->m_A = 10.0f;
+ activationDesc->m_B = 5.0f;
+ activationDesc->m_Function = armnn::ActivationFunction::BoundedReLu;
+
+ layer->SetAdditionalInfoForObject(activationDesc);
+
+ // Creates extra layers.
+ Layer* const input1 = graph.AddLayer<InputLayer>(1, "input1");
+ Layer* const input2 = graph.AddLayer<InputLayer>(2, "input2");
+ Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
+
+ // Connects up.
+ armnn::TensorInfo tensorInfo({2, 3}, DataType);
+ Connect(input1, layer, tensorInfo, 0, 0);
+ Connect(input2, layer, tensorInfo, 0, 1);
+ Connect(layer, output, tensorInfo);
+ CreateTensorHandles(graph, factory);
+
+ // Check that the additional information can be queried from the layer
+ std::shared_ptr<ActivationDescriptor>
+ activationDescPtr = layer->GetAdditionalInformation<ActivationDescriptor>();
+
+ BOOST_ASSERT(static_cast<float>(activationDescPtr->m_A) == 10.0f);
+ BOOST_ASSERT(static_cast<float>(activationDescPtr->m_B) == 5.0f);
+ BOOST_ASSERT(
+ static_cast<ActivationFunction>(activationDescPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
+ );
+
+ // Makes the workload and checks it.
+ auto workload = MakeAndCheckWorkload<WorkloadType>(*layer, factory);
+
+ DescriptorType queueDescriptor = workload->GetData();
+
+ const ActivationDescriptor* queueDescBlobPtr =
+ queueDescriptor.template GetAdditionalInformation<ActivationDescriptor>();
+ IgnoreUnused(queueDescBlobPtr);
+ BOOST_ASSERT(static_cast<float>(queueDescBlobPtr->m_A) == 10.0f);
+ BOOST_ASSERT(static_cast<float>(queueDescBlobPtr->m_B) == 5.0f);
+ BOOST_ASSERT(
+ static_cast<ActivationFunction>(queueDescBlobPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
+ );
+
+ BOOST_TEST(queueDescriptor.m_Inputs.size() == 2);
+ BOOST_TEST(queueDescriptor.m_Outputs.size() == 1);
+
+ return workload;
+}
+
+template<typename WorkloadType,
+ typename DescriptorType,
+ armnn::DataType DataType>
+std::unique_ptr<WorkloadType> CreateMultiplicationWithBlobWorkloadTest(armnn::IWorkloadFactory& factory,
+ armnn::Graph& graph)
+{
+ // Creates the layer we're testing.
+ MultiplicationLayer* const layer = graph.AddLayer<MultiplicationLayer>("layer");
+
+ auto activationDesc = std::make_shared<ActivationDescriptor>();
+ activationDesc->m_A = 10.0f;
+ activationDesc->m_B = 5.0f;
+ activationDesc->m_Function = armnn::ActivationFunction::BoundedReLu;
+
+ layer->SetAdditionalInfoForObject(activationDesc);
+
+ // Creates extra layers.
+ Layer* const input1 = graph.AddLayer<InputLayer>(1, "input1");
+ Layer* const input2 = graph.AddLayer<InputLayer>(2, "input2");
+ Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
+
+ // Connects up.
+ armnn::TensorInfo tensorInfo({2, 3}, DataType);
+ Connect(input1, layer, tensorInfo, 0, 0);
+ Connect(input2, layer, tensorInfo, 0, 1);
+ Connect(layer, output, tensorInfo);
+ CreateTensorHandles(graph, factory);
+
+ // Check that the additional information can be queried from the layer
+ std::shared_ptr<ActivationDescriptor>
+ activationDescPtr = layer->GetAdditionalInformation<ActivationDescriptor>();
+
+ BOOST_ASSERT(static_cast<float>(activationDescPtr->m_A) == 10.0f);
+ BOOST_ASSERT(static_cast<float>(activationDescPtr->m_B) == 5.0f);
+ BOOST_ASSERT(
+ static_cast<ActivationFunction>(activationDescPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
+ );
+
+ // Makes the workload and checks it.
+ auto workload = MakeAndCheckWorkload<WorkloadType>(*layer, factory);
+
+ DescriptorType queueDescriptor = workload->GetData();
+ BOOST_TEST(queueDescriptor.m_Inputs.size() == 2);
+ BOOST_TEST(queueDescriptor.m_Outputs.size() == 1);
+ const ActivationDescriptor* queueDescBlobPtr =
+ queueDescriptor.template GetAdditionalInformation<ActivationDescriptor>();
+ IgnoreUnused(queueDescBlobPtr);
+ BOOST_ASSERT(static_cast<float>(queueDescBlobPtr->m_A) == 10.0f);
+ BOOST_ASSERT(static_cast<float>(queueDescBlobPtr->m_B) == 5.0f);
+ BOOST_ASSERT(
+ static_cast<ActivationFunction>(queueDescBlobPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
+ );
+
+ return workload;// Returns so we can do extra, backend-specific tests.
+}
+
+template<typename WorkloadType,
+ typename DescriptorType,
+ armnn::DataType DataType>
+std::unique_ptr<WorkloadType> CreateAdditionWithBlobWorkloadTest(armnn::IWorkloadFactory& factory,
+ armnn::Graph& graph)
+{
+ // Creates the layer we're testing.
+ AdditionLayer* const layer = graph.AddLayer<AdditionLayer>("layer");
+
+ auto activationDesc = std::make_shared<ActivationDescriptor>();
+ activationDesc->m_A = 10.0f;
+ activationDesc->m_B = 5.0f;
+ activationDesc->m_Function = armnn::ActivationFunction::BoundedReLu;
+
+ layer->SetAdditionalInfoForObject(activationDesc);
+
+ // Creates extra layers.
+ Layer* const input1 = graph.AddLayer<InputLayer>(1, "input1");
+ Layer* const input2 = graph.AddLayer<InputLayer>(2, "input2");
+ Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
+
+ // Connects up.
+ armnn::TensorInfo tensorInfo({2, 3}, DataType);
+ Connect(input1, layer, tensorInfo, 0, 0);
+ Connect(input2, layer, tensorInfo, 0, 1);
+ Connect(layer, output, tensorInfo);
+ CreateTensorHandles(graph, factory);
+
+ // Check that the additional information can be queried from the layer
+ std::shared_ptr<ActivationDescriptor>
+ activationDescPtr = layer->template GetAdditionalInformation<ActivationDescriptor>();
+
+ BOOST_ASSERT(static_cast<float>(activationDescPtr->m_A) == 10.0f);
+ BOOST_ASSERT(static_cast<float>(activationDescPtr->m_B) == 5.0f);
+ BOOST_ASSERT(
+ static_cast<ActivationFunction>(activationDescPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
+ );
+
+ // Makes the workload and checks it.
+ auto workload = MakeAndCheckWorkload<WorkloadType>(*layer, factory);
+
+ DescriptorType queueDescriptor = workload->GetData();
+ const ActivationDescriptor* queueDescBlobPtr =
+ queueDescriptor.template GetAdditionalInformation<ActivationDescriptor>();
+ IgnoreUnused(queueDescBlobPtr);
+ BOOST_TEST(queueDescriptor.m_Inputs.size() == 2);
+ BOOST_TEST(queueDescriptor.m_Outputs.size() == 1);
+ BOOST_ASSERT(static_cast<float>(queueDescBlobPtr->m_A) == 10.0f);
+ BOOST_ASSERT(static_cast<float>(queueDescBlobPtr->m_B) == 5.0f);
+ BOOST_ASSERT(
+ static_cast<ActivationFunction>(queueDescBlobPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
+ );
+
+ return workload;
+}
+
+template <typename WorkloadType,
typename DescriptorType,
armnn::DataType DataType>
std::unique_ptr<WorkloadType> CreateElementwiseUnaryWorkloadTest(armnn::IWorkloadFactory & factory,
@@ -218,6 +388,87 @@
return workload;
}
+template <typename BatchNormalizationWorkloadType, armnn::DataType DataType>
+std::unique_ptr<BatchNormalizationWorkloadType> CreateBatchNormalizationWithBlobWorkloadTest(
+ armnn::IWorkloadFactory& factory, armnn::Graph& graph, DataLayout dataLayout = DataLayout::NCHW)
+{
+ TensorShape tensorShape;
+ switch (dataLayout)
+ {
+ case DataLayout::NHWC:
+ tensorShape = { 2, 4, 4, 3 };
+ break;
+ case DataLayout::NCHW:
+ default:
+ tensorShape = { 2, 3, 4, 4 };
+ }
+
+ // Creates the layer we're testing.
+ BatchNormalizationDescriptor layerDesc;
+ layerDesc.m_Eps = 0.05f;
+ layerDesc.m_DataLayout = dataLayout;
+
+ BatchNormalizationLayer* const layer = graph.AddLayer<BatchNormalizationLayer>(layerDesc, "layer");
+
+ armnn::TensorInfo weightInfo({3}, DataType);
+ layer->m_Mean = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
+ layer->m_Variance = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
+ layer->m_Beta = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
+ layer->m_Gamma = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
+ layer->m_Mean->Allocate();
+ layer->m_Variance->Allocate();
+ layer->m_Beta->Allocate();
+ layer->m_Gamma->Allocate();
+
+ auto activationDesc = std::make_shared<ActivationDescriptor>();
+ activationDesc->m_A = 10.0f;
+ activationDesc->m_B = 5.0f;
+ activationDesc->m_Function = armnn::ActivationFunction::BoundedReLu;
+
+ layer->SetAdditionalInfoForObject(activationDesc);
+
+ // Check that the additional information can be queried from the layer
+ std::shared_ptr<ActivationDescriptor> activationDescPtr = layer->GetAdditionalInformation<ActivationDescriptor>();
+ BOOST_ASSERT(static_cast<float>(activationDescPtr->m_A) == 10.0f);
+ BOOST_ASSERT(static_cast<float>(activationDescPtr->m_B) == 5.0f);
+ BOOST_ASSERT(
+ static_cast<ActivationFunction>(activationDescPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
+ );
+
+ // Creates extra layers.
+ Layer* const input = graph.AddLayer<InputLayer>(0, "input");
+ Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
+
+ // Connects up.
+ armnn::TensorInfo tensorInfo(tensorShape, DataType);
+ Connect(input, layer, tensorInfo);
+ Connect(layer, output, tensorInfo);
+ CreateTensorHandles(graph, factory);
+
+ // Makes the workload and checks it.
+ auto workload = MakeAndCheckWorkload<BatchNormalizationWorkloadType>(*layer, factory);
+ BatchNormalizationQueueDescriptor queueDescriptor = workload->GetData();
+ const ActivationDescriptor* queueDescBlobPtr = queueDescriptor.GetAdditionalInformation<ActivationDescriptor>();
+ IgnoreUnused(queueDescBlobPtr);
+ BOOST_ASSERT(static_cast<float>(queueDescBlobPtr->m_A) == 10.0f);
+ BOOST_ASSERT(static_cast<float>(queueDescBlobPtr->m_B) == 5.0f);
+ BOOST_ASSERT(
+ static_cast<ActivationFunction>(queueDescBlobPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
+ );
+
+ BOOST_TEST(queueDescriptor.m_Parameters.m_Eps == 0.05f);
+ BOOST_TEST(queueDescriptor.m_Inputs.size() == 1);
+ BOOST_TEST(queueDescriptor.m_Outputs.size() == 1);
+ BOOST_TEST((queueDescriptor.m_Mean->GetTensorInfo() == TensorInfo({3}, DataType)));
+ BOOST_TEST((queueDescriptor.m_Variance->GetTensorInfo() == TensorInfo({3}, DataType)));
+ BOOST_TEST((queueDescriptor.m_Gamma->GetTensorInfo() == TensorInfo({3}, DataType)));
+ BOOST_TEST((queueDescriptor.m_Beta->GetTensorInfo() == TensorInfo({3}, DataType)));
+ BOOST_TEST((queueDescriptor.m_Parameters.m_DataLayout == dataLayout));
+
+ // Returns so we can do extra, backend-specific tests.
+ return workload;
+}
+
template <typename Convolution2dWorkload, armnn::DataType DataType>
std::unique_ptr<Convolution2dWorkload> CreateConvolution2dWorkloadTest(armnn::IWorkloadFactory& factory,
armnn::Graph& graph,
@@ -279,6 +530,92 @@
return workload;
}
+template<typename Convolution2dWorkload, armnn::DataType DataType>
+std::unique_ptr<Convolution2dWorkload> CreateConvolution2dFusedActivationWithBlobWorkloadTest(
+ armnn::IWorkloadFactory& factory,
+ armnn::Graph& graph,
+ DataLayout dataLayout = DataLayout::NCHW,
+ const ModelOptions& modelOptions = {})
+{
+ // Creates the layer we're testing.
+ Convolution2dDescriptor layerDesc;
+ layerDesc.m_PadLeft = 3;
+ layerDesc.m_PadRight = 3;
+ layerDesc.m_PadTop = 1;
+ layerDesc.m_PadBottom = 1;
+ layerDesc.m_StrideX = 2;
+ layerDesc.m_StrideY = 4;
+ layerDesc.m_BiasEnabled = true;
+ layerDesc.m_DataLayout = dataLayout;
+
+
+ Convolution2dLayer* const layer = graph.AddLayer<Convolution2dLayer>(layerDesc, "layer");
+
+ TensorShape weightShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 3, 5, 3} : TensorShape{2, 5, 3, 3};
+ TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 3, 8, 16} : TensorShape{2, 8, 16, 3};
+ TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 2, 2, 10} : TensorShape{2, 2, 10, 2};
+
+ layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(TensorInfo(weightShape, DataType));
+ layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(TensorInfo({2}, GetBiasDataType(DataType)));
+
+ layer->m_Weight->Allocate();
+ layer->m_Bias->Allocate();
+
+ auto activationDesc = std::make_shared<ActivationDescriptor>();
+ activationDesc->m_A = 10.0f;
+ activationDesc->m_B = 5.0f;
+ activationDesc->m_Function = armnn::ActivationFunction::BoundedReLu;
+
+ layer->SetAdditionalInfoForObject(activationDesc);
+
+ // Check that the additional information can be queried from the layer
+ std::shared_ptr<ActivationDescriptor> activationDescPtr = layer->GetAdditionalInformation<ActivationDescriptor>();
+
+ BOOST_ASSERT(static_cast<float>(activationDescPtr->m_A) == 10.0f);
+ BOOST_ASSERT(static_cast<float>(activationDescPtr->m_B) == 5.0f);
+ BOOST_ASSERT(
+ static_cast<ActivationFunction>(activationDescPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
+ );
+
+ // Creates extra layers.
+ Layer* const input = graph.AddLayer<InputLayer>(0, "input");
+ Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
+
+ // Connects up.
+ Connect(input, layer, TensorInfo(inputShape, DataType));
+ Connect(layer, output, TensorInfo(outputShape, DataType));
+ CreateTensorHandles(graph, factory);
+
+ // Makes the workload and checks it.
+ auto workload = MakeAndCheckWorkload<Convolution2dWorkload>(*layer, factory, modelOptions);
+
+ Convolution2dQueueDescriptor queueDescriptor = workload->GetData();
+ const ActivationDescriptor* queueDescBlobPtr = queueDescriptor.GetAdditionalInformation<ActivationDescriptor>();
+ IgnoreUnused(queueDescBlobPtr);
+ BOOST_ASSERT(static_cast<float>(queueDescBlobPtr->m_A) == 10.0f);
+ BOOST_ASSERT(static_cast<float>(queueDescBlobPtr->m_B) == 5.0f);
+ BOOST_ASSERT(
+ static_cast<ActivationFunction>(queueDescBlobPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
+ );
+
+ BOOST_TEST(queueDescriptor.m_Parameters.m_StrideX == 2);
+ BOOST_TEST(queueDescriptor.m_Parameters.m_StrideY == 4);
+ BOOST_TEST(queueDescriptor.m_Parameters.m_PadLeft == 3);
+ BOOST_TEST(queueDescriptor.m_Parameters.m_PadRight == 3);
+ BOOST_TEST(queueDescriptor.m_Parameters.m_PadTop == 1);
+ BOOST_TEST(queueDescriptor.m_Parameters.m_PadBottom == 1);
+ BOOST_TEST(queueDescriptor.m_Parameters.m_BiasEnabled);
+ BOOST_TEST((queueDescriptor.m_Parameters.m_DataLayout == dataLayout));
+ BOOST_TEST(queueDescriptor.m_Outputs.size() == 1);
+ BOOST_TEST((queueDescriptor.m_Weight->GetTensorInfo() == TensorInfo(weightShape, DataType)));
+ BOOST_TEST((queueDescriptor.m_Bias->GetTensorInfo() ==
+ TensorInfo({2}, GetBiasDataType(DataType))));
+ BOOST_TEST(queueDescriptor.m_Inputs.size() == 1);
+
+ // Returns so we can do extra, backend-specific tests.
+ return workload;
+}
+
template <typename Convolution2dWorkload, armnn::DataType DataType>
std::unique_ptr<Convolution2dWorkload> CreateConvolution2dWorkloadFastMathTest(armnn::IWorkloadFactory& factory,
armnn::Graph& graph,
@@ -893,6 +1230,75 @@
return workload;
}
+template <typename FullyConnectedWorkload, armnn::DataType DataType>
+std::unique_ptr<FullyConnectedWorkload> CreateFullyConnectedWithBlobWorkloadTest
+ (armnn::IWorkloadFactory& factory,
+ armnn::Graph& graph)
+{
+ // Creates the layer we're testing.
+ FullyConnectedDescriptor layerDesc;
+ layerDesc.m_BiasEnabled = true;
+ layerDesc.m_TransposeWeightMatrix = true;
+
+ FullyConnectedLayer* const layer = graph.AddLayer<FullyConnectedLayer>(layerDesc, "layer");
+
+ float inputsQScale = DataType == armnn::DataType::QAsymmU8 ? 1.0f : 0.0;
+ float outputQScale = DataType == armnn::DataType::QAsymmU8 ? 2.0f : 0.0;
+
+ layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(TensorInfo({7, 20}, DataType, inputsQScale, 0));
+ layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(TensorInfo({7}, GetBiasDataType(DataType), inputsQScale));
+ layer->m_Weight->Allocate();
+ layer->m_Bias->Allocate();
+
+ auto activationDesc = std::make_shared<ActivationDescriptor>();
+ activationDesc->m_A = 10.0f;
+ activationDesc->m_B = 5.0f;
+ activationDesc->m_Function = armnn::ActivationFunction::BoundedReLu;
+
+ layer->SetAdditionalInfoForObject(activationDesc);
+
+ // Check that the additional information can be queried from the layer
+ std::shared_ptr<ActivationDescriptor> activationDescPtr = layer->GetAdditionalInformation<ActivationDescriptor>();
+ BOOST_ASSERT(static_cast<float>(activationDescPtr->m_A) == 10.0f);
+ BOOST_ASSERT(static_cast<float>(activationDescPtr->m_B) == 5.0f);
+ BOOST_ASSERT(static_cast<ActivationFunction>(activationDescPtr->m_Function) ==
+ armnn::ActivationFunction::BoundedReLu);
+
+ // Creates extra layers.
+ Layer* const input = graph.AddLayer<InputLayer>(0, "input");
+ Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
+
+ // Connects up.
+ Connect(input, layer, TensorInfo({3, 1, 4, 5}, DataType, inputsQScale));
+ Connect(layer, output, TensorInfo({3, 7}, DataType, outputQScale));
+ CreateTensorHandles(graph, factory);
+
+ // Makes the workload and checks it.
+ auto workload = MakeAndCheckWorkload<FullyConnectedWorkload>(*layer, factory);
+
+ FullyConnectedQueueDescriptor queueDescriptor = workload->GetData();
+
+ const ActivationDescriptor* queueDescBlobPtr = queueDescriptor.GetAdditionalInformation<ActivationDescriptor>();
+ IgnoreUnused(queueDescBlobPtr);
+
+ BOOST_ASSERT(static_cast<float>(queueDescBlobPtr->m_A) == 10.0f);
+ BOOST_ASSERT(static_cast<float>(queueDescBlobPtr->m_B) == 5.0f);
+ BOOST_ASSERT(
+ static_cast<ActivationFunction>(queueDescBlobPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
+ );
+
+ BOOST_TEST(queueDescriptor.m_Parameters.m_BiasEnabled == true);
+ BOOST_TEST(queueDescriptor.m_Parameters.m_TransposeWeightMatrix == true);
+ BOOST_TEST(queueDescriptor.m_Inputs.size() == 1);
+ BOOST_TEST(queueDescriptor.m_Outputs.size() == 1);
+ BOOST_TEST((queueDescriptor.m_Weight->GetTensorInfo() == TensorInfo({7, 20}, DataType, inputsQScale)));
+ BOOST_TEST((queueDescriptor.m_Bias->GetTensorInfo() == TensorInfo({7}, GetBiasDataType(DataType), inputsQScale)));
+
+ // Returns so we can do extra, backend-specific tests.
+ return workload;
+}
+
+
template <typename NormalizationWorkload, armnn::DataType DataType>
std::unique_ptr<NormalizationWorkload> CreateNormalizationWorkloadTest(armnn::IWorkloadFactory& factory,
armnn::Graph& graph,
diff --git a/src/backends/backendsCommon/WorkloadData.hpp b/src/backends/backendsCommon/WorkloadData.hpp
index c563626..952ddc3 100644
--- a/src/backends/backendsCommon/WorkloadData.hpp
+++ b/src/backends/backendsCommon/WorkloadData.hpp
@@ -29,15 +29,23 @@
{
std::vector<ITensorHandle*> m_Inputs;
std::vector<ITensorHandle*> m_Outputs;
+ void* m_AdditionalInfoObject;
void ValidateInputsOutputs(const std::string& descName,
unsigned int numExpectedIn,
unsigned int numExpectedOut) const;
+ template<typename T>
+ const T* GetAdditionalInformation()
+ {
+ return static_cast<T*>(m_AdditionalInfoObject);
+ }
protected:
~QueueDescriptor() = default;
- QueueDescriptor() = default;
+ QueueDescriptor()
+ : m_AdditionalInfoObject(nullptr)
+ {}
QueueDescriptor(QueueDescriptor const&) = default;
QueueDescriptor& operator=(QueueDescriptor const&) = default;
};
diff --git a/src/backends/reference/test/RefCreateWorkloadTests.cpp b/src/backends/reference/test/RefCreateWorkloadTests.cpp
index 6e2217c..0f86e7e 100644
--- a/src/backends/reference/test/RefCreateWorkloadTests.cpp
+++ b/src/backends/reference/test/RefCreateWorkloadTests.cpp
@@ -89,6 +89,55 @@
TensorInfo({ 2, 3 }, DataType));
}
+BOOST_AUTO_TEST_CASE(CreateSubtractionWorkloadWithBlobTest)
+{
+ Graph graph;
+ RefWorkloadFactory factory = GetFactory();
+ armnn::DataType DataType = armnn::DataType::Float32;
+
+ auto workload = CreateSubtractionWithBlobWorkloadTest<RefSubtractionWorkload<>,
+ SubtractionQueueDescriptor,
+ armnn::DataType::Float32>
+ (factory, graph);
+
+ CheckInputsOutput(std::move(workload),
+ TensorInfo({ 2, 3 }, DataType),
+ TensorInfo({ 2, 3 }, DataType),
+ TensorInfo({ 2, 3 }, DataType));
+}
+
+BOOST_AUTO_TEST_CASE(CreateAdditionWorkloadWithBlobTest)
+{
+ Graph graph;
+ RefWorkloadFactory factory = GetFactory();
+ armnn::DataType DataType = armnn::DataType::Float32;
+
+ auto workload = CreateAdditionWithBlobWorkloadTest<RefAdditionWorkload<>,
+ AdditionQueueDescriptor,
+ armnn::DataType::Float32>(factory, graph);
+
+ CheckInputsOutput(std::move(workload),
+ TensorInfo({ 2, 3 }, DataType),
+ TensorInfo({ 2, 3 }, DataType),
+ TensorInfo({ 2, 3 }, DataType));
+}
+
+BOOST_AUTO_TEST_CASE(CreateMultiplicationWorkloadWithBlobTest)
+{
+ Graph graph;
+ RefWorkloadFactory factory = GetFactory();
+ armnn::DataType DataType = armnn::DataType::Float32;
+
+ auto workload = CreateMultiplicationWithBlobWorkloadTest<RefMultiplicationWorkload<>,
+ MultiplicationQueueDescriptor,
+ armnn::DataType::Float32>(factory, graph);
+
+ CheckInputsOutput(std::move(workload),
+ TensorInfo({2, 3}, DataType),
+ TensorInfo({2, 3}, DataType),
+ TensorInfo({2, 3}, DataType));
+}
+
BOOST_AUTO_TEST_CASE(CreateAdditionFloatWorkload)
{
RefCreateElementwiseWorkloadTest<RefAdditionWorkload<>,
@@ -262,6 +311,24 @@
CheckInputOutput(std::move(workload), TensorInfo(inputShape, DataType), TensorInfo(outputShape, DataType));
}
+BOOST_AUTO_TEST_CASE(CreateBatchNormalizationWithBlobFloat32Workload)
+{
+ Graph graph;
+ RefWorkloadFactory factory = GetFactory();
+ auto dataType = armnn::DataType::Float32;
+ auto workload = CreateBatchNormalizationWorkloadTest<RefBatchNormalizationWorkload,
+ armnn::DataType::Float32>(factory, graph, DataLayout::NHWC);
+
+ TensorShape inputShape;
+ TensorShape outputShape;
+
+ inputShape = { 2, 4, 4, 3 };
+ outputShape = { 2, 4, 4, 3 };
+
+ // Checks that outputs and inputs are as we expect them (see definition of CreateBatchNormalizationWorkloadTest).
+ CheckInputOutput(std::move(workload), TensorInfo(inputShape, dataType), TensorInfo(outputShape, dataType));
+}
+
BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloat32Workload)
{
RefCreateBatchNormalizationWorkloadTest<RefBatchNormalizationWorkload,armnn::DataType::Float32>
@@ -360,6 +427,25 @@
RefCreateConvolution2dWorkloadTest(DataLayout::NHWC);
}
+BOOST_AUTO_TEST_CASE(CreateConvolution2dWithBlobWorkload)
+{
+ DataLayout dataLayout = DataLayout::NHWC;
+ Graph graph;
+ RefWorkloadFactory factory = GetFactory();
+ auto workload = CreateConvolution2dFusedActivationWithBlobWorkloadTest<RefConvolution2dWorkload, DataType::Float32>
+ (factory, graph, dataLayout);
+
+ TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? std::initializer_list<unsigned int>({2, 3, 8, 16})
+ : std::initializer_list<unsigned int>({2, 8, 16, 3});
+ TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? std::initializer_list<unsigned int>({2, 2, 2, 10})
+ : std::initializer_list<unsigned int>({2, 2, 10, 2});
+
+ // Checks that outputs and inputs are as we expect them (see definition of CreateConvolution2dWorkloadTest).
+ CheckInputOutput(std::move(workload),
+ TensorInfo(inputShape, DataType::Float32),
+ TensorInfo(outputShape, DataType::Float32));
+}
+
static void RefCreateDepthwiseConvolutionWorkloadTest(DataLayout dataLayout)
{
Graph graph;
@@ -383,6 +469,21 @@
RefCreateDepthwiseConvolutionWorkloadTest(DataLayout::NHWC);
}
+BOOST_AUTO_TEST_CASE(RefCreateFullyConnectedWithBlobWorkloadTest)
+{
+ Graph graph;
+ RefWorkloadFactory factory = GetFactory();
+ auto workload = CreateFullyConnectedWithBlobWorkloadTest<RefFullyConnectedWorkload,
+ armnn::DataType::Float32>(factory, graph);
+
+ // Checks that outputs and inputs are as we expect them (see definition of CreateFullyConnectedWorkloadTest).
+ float inputsQScale = 0.0f;
+ float outputQScale = 0.0f;
+ CheckInputOutput(std::move(workload),
+ TensorInfo({ 3, 1, 4, 5 }, armnn::DataType::Float32, inputsQScale),
+ TensorInfo({ 3, 7 }, armnn::DataType::Float32, outputQScale));
+}
+
template <typename FullyConnectedWorkloadType, armnn::DataType DataType>
static void RefCreateFullyConnectedWorkloadTest()
{