aboutsummaryrefslogtreecommitdiff
path: root/arm_compute
diff options
context:
space:
mode:
authorSheri Zhang <sheri.zhang@arm.com>2020-05-27 15:03:48 +0100
committerSheri Zhang <sheri.zhang@arm.com>2020-06-16 13:12:48 +0000
commit16dddd2af57a71ca10d62a4412d014f859720d2c (patch)
tree6478e50fc7b72775f781562508bfaf87e6d935a9 /arm_compute
parentbcd2352d7fd99a2f6aab220fa0c3b3f3119a1a4c (diff)
downloadComputeLibrary-16dddd2af57a71ca10d62a4412d014f859720d2c.tar.gz
COMPMID-3381: Implement graph example for YoLo v3 output detector
Add sub/exp/splitv support in graph api Signed-off-by: Sheri Zhang <sheri.zhang@arm.com> Change-Id: I4e08cc19a46655717068b12c93d67e619a595d9a Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/3309 Reviewed-by: Georgios Pinitas <georgios.pinitas@arm.com> Tested-by: Arm Jenkins <bsgcomp@arm.com> Comments-Addressed: Arm Jenkins <bsgcomp@arm.com>
Diffstat (limited to 'arm_compute')
-rw-r--r--arm_compute/graph/LayerDescriptors.h25
-rw-r--r--arm_compute/graph/TypePrinter.h3
-rw-r--r--arm_compute/graph/Types.h9
-rw-r--r--arm_compute/graph/backends/FunctionHelpers.h48
-rw-r--r--arm_compute/graph/backends/ValidateHelpers.h73
-rw-r--r--arm_compute/graph/nodes/EltwiseLayerNode.h40
-rw-r--r--arm_compute/graph/nodes/SplitLayerNode.h20
7 files changed, 209 insertions, 9 deletions
diff --git a/arm_compute/graph/LayerDescriptors.h b/arm_compute/graph/LayerDescriptors.h
index d8e6a6a87b..ba53622298 100644
--- a/arm_compute/graph/LayerDescriptors.h
+++ b/arm_compute/graph/LayerDescriptors.h
@@ -89,6 +89,31 @@ struct EltwiseLayerDescriptor
ActivationLayerInfo fused_activation; /**< Fused activation info */
};
+/** Unary Elementwise layer descriptor */
+struct UnaryEltwiseLayerDescriptor
+{
+ /** Constructor
+ *
+ * @param[in] op Unary element-wise operation to perform
+ * @param[in] out_quant_info (Optional) Output quantization information. Defaults to empty @ref QuantizationInfo
+ * @param[in] c_policy (Optional) Convert policy used for the operation. Defaults to @ref ConvertPolicy::SATURATE
+ * @param[in] r_policy (Optional) Rounding policy used for the operation. Defaults to @ref RoundingPolicy::TO_ZERO
+ * @param[in] fused_activation (Optional) Fused activation information. Defaults to empty (identity) @ref ActivationLayerInfo
+ */
+ UnaryEltwiseLayerDescriptor(UnaryEltwiseOperation op, QuantizationInfo out_quant_info = QuantizationInfo(), ConvertPolicy c_policy = ConvertPolicy::SATURATE,
+ RoundingPolicy r_policy = RoundingPolicy::TO_ZERO,
+ ActivationLayerInfo fused_activation = ActivationLayerInfo())
+ : op(op), out_quant_info(out_quant_info), c_policy(c_policy), r_policy(r_policy), fused_activation(fused_activation)
+ {
+ }
+
+ UnaryEltwiseOperation op; /**< Unary element-wise operation to perform */
+ QuantizationInfo out_quant_info; /**< Output quantization information */
+ ConvertPolicy c_policy; /**< Convert policy */
+ RoundingPolicy r_policy; /**< Rounding policy */
+ ActivationLayerInfo fused_activation; /**< Fused activation info */
+};
+
/** Deconvolution layer descriptor */
struct DeconvolutionLayerDescriptor
{
diff --git a/arm_compute/graph/TypePrinter.h b/arm_compute/graph/TypePrinter.h
index d56407b52b..dea055a83b 100644
--- a/arm_compute/graph/TypePrinter.h
+++ b/arm_compute/graph/TypePrinter.h
@@ -98,6 +98,9 @@ inline ::std::ostream &operator<<(::std::ostream &os, const NodeType &node_type)
case NodeType::EltwiseLayer:
os << "EltwiseLayer";
break;
+ case NodeType::UnaryEltwiseLayer:
+ os << "UnaryEltwiseLayer";
+ break;
case NodeType::FlattenLayer:
os << "FlattenLayer";
break;
diff --git a/arm_compute/graph/Types.h b/arm_compute/graph/Types.h
index 296f757c9b..422069238d 100644
--- a/arm_compute/graph/Types.h
+++ b/arm_compute/graph/Types.h
@@ -103,7 +103,13 @@ enum class EltwiseOperation
{
Add, /**< Arithmetic addition */
Sub, /**< Arithmetic subtraction */
- Mul /**< Arithmetic multiplication */
+ Mul, /**< Arithmetic multiplication */
+};
+
+/** Supported Unary Element-wise operations */
+enum class UnaryEltwiseOperation
+{
+ Exp /**< Exp */
};
/** Supported Convolution layer methods */
@@ -168,6 +174,7 @@ enum class NodeType
SplitLayer,
StackLayer,
UpsampleLayer,
+ UnaryEltwiseLayer,
YOLOLayer,
Input,
diff --git a/arm_compute/graph/backends/FunctionHelpers.h b/arm_compute/graph/backends/FunctionHelpers.h
index 975e5fe55e..e21b8ed288 100644
--- a/arm_compute/graph/backends/FunctionHelpers.h
+++ b/arm_compute/graph/backends/FunctionHelpers.h
@@ -816,6 +816,54 @@ std::unique_ptr<IFunction> create_eltwise_layer(EltwiseLayerNode &node)
return RETURN_UNIQUE_PTR(func);
}
+/** Create a backend unary element-wise operation layer function
+ *
+ * @tparam UnaryEltwiseFunctions Backend unary element-wise function
+ * @tparam TargetInfo Target-specific information
+ *
+ * @param[in] node Node to create the backend function for
+ *
+ * @return Backend unary element-wise operation layer function
+ */
+template <typename UnaryEltwiseFunctions, typename TargetInfo>
+std::unique_ptr<IFunction> create_unary_eltwise_layer(UnaryEltwiseLayerNode &node)
+{
+ validate_node<TargetInfo>(node, 1 /* expected inputs */, 1 /* expected outputs */);
+
+ // Extract IO and info
+ typename TargetInfo::TensorType *input = get_backing_tensor<TargetInfo>(node.input(0));
+ typename TargetInfo::TensorType *output = get_backing_tensor<TargetInfo>(node.output(0));
+ const UnaryEltwiseOperation eltwise_op = node.eltwise_descriptor().op;
+
+ ARM_COMPUTE_ERROR_ON(input == nullptr);
+ ARM_COMPUTE_ERROR_ON(output == nullptr);
+
+ std::unique_ptr<IFunction> func = nullptr;
+ std::string func_name;
+ if(eltwise_op == UnaryEltwiseOperation::Exp)
+ {
+ std::tie(func, func_name) = create_named_function<typename UnaryEltwiseFunctions::Exp>(
+ std::string("Exp"),
+ input, output);
+ }
+ else
+ {
+ ARM_COMPUTE_ERROR("Unsupported unary element-wise operation!");
+ }
+
+ // Log info
+ ARM_COMPUTE_LOG_GRAPH_INFO("Instantiated "
+ << node.name()
+ << " Type: " << node.type()
+ << " Target: " << TargetInfo::TargetType
+ << " Operation: " << func_name
+ << " Data Type: " << input->info()->data_type()
+ << " Shape: " << input->info()->tensor_shape()
+ << std::endl);
+
+ return RETURN_UNIQUE_PTR(func);
+}
+
/** Create a backend flatten layer function
*
* @tparam FlattenLayerFunction Backend flatten function
diff --git a/arm_compute/graph/backends/ValidateHelpers.h b/arm_compute/graph/backends/ValidateHelpers.h
index 673caf9eac..d689c1f89d 100644
--- a/arm_compute/graph/backends/ValidateHelpers.h
+++ b/arm_compute/graph/backends/ValidateHelpers.h
@@ -579,6 +579,79 @@ Status validate_yolo_layer(YOLOLayerNode &node)
// Validate function
return YOLOLayer::validate(input, output, node.activation_info(), node.num_classes());
}
+/** Validates a element-wise layer node
+ *
+ * @param[in] node Node to validate
+ *
+ * @return Status
+ */
+template <typename EltwiseLayerFunctions>
+Status validate_eltwise_Layer(EltwiseLayerNode &node)
+{
+ ARM_COMPUTE_LOG_GRAPH_VERBOSE("Validating EltwiseLayer node with ID : " << node.id() << " and Name: " << node.name() << std::endl);
+ ARM_COMPUTE_RETURN_ERROR_ON(node.num_inputs() != 2);
+ ARM_COMPUTE_RETURN_ERROR_ON(node.num_outputs() != 1);
+
+ // Extract input and output
+ const arm_compute::ITensorInfo *input1 = detail::get_backing_tensor_info(node.input(0));
+ const arm_compute::ITensorInfo *input2 = detail::get_backing_tensor_info(node.input(1));
+ const arm_compute::ITensorInfo *output = get_backing_tensor_info(node.output(0));
+ const EltwiseOperation eltwise_op = node.eltwise_operation();
+ const ConvertPolicy convert_policy = node.convert_policy();
+ const RoundingPolicy round_policy = node.rounding_policy();
+ const ActivationLayerInfo act_info = node.fused_activation();
+ const QuantizationInfo quant_info = node.output_quant_info();
+ const float scale = (quant_info.scale().empty()) ? 1.0f : quant_info.scale()[0];
+
+ // Validate function
+ if(eltwise_op == EltwiseOperation::Add)
+ {
+ return EltwiseLayerFunctions::ArithmeticAddition::validate(input1, input2, output, convert_policy, act_info);
+ }
+ else if(eltwise_op == EltwiseOperation::Sub)
+ {
+ return EltwiseLayerFunctions::ArithmeticSubtraction::validate(input1, input2, output, convert_policy, act_info);
+ }
+ else if(eltwise_op == EltwiseOperation::Mul)
+ {
+ return EltwiseLayerFunctions::PixelWiseMultiplication::validate(input1, input2, output, scale, convert_policy, round_policy, act_info);
+ }
+ else
+ {
+ ARM_COMPUTE_ERROR("Unsupported element-wise operation!");
+ }
+ return Status{};
+}
+/** Validates a unary element-wise layer node
+ *
+ * @param[in] node Node to validate
+ *
+ * @return Status
+ */
+template <typename UnaryEltwiseLayerFunctions>
+Status validate_unary_eltwise_layer(UnaryEltwiseLayerNode &node)
+{
+ ARM_COMPUTE_LOG_GRAPH_VERBOSE("Validating EltwiseLayer node with ID : " << node.id() << " and Name: " << node.name() << std::endl);
+ ARM_COMPUTE_RETURN_ERROR_ON(node.num_inputs() != 1);
+ ARM_COMPUTE_RETURN_ERROR_ON(node.num_outputs() != 1);
+
+ // Extract input and output
+ arm_compute::ITensorInfo *input = detail::get_backing_tensor_info(node.input(0));
+ arm_compute::ITensorInfo *output = get_backing_tensor_info(node.output(0));
+ const UnaryEltwiseOperation eltwise_op = node.eltwise_descriptor().op;
+
+ // Validate function
+ if(eltwise_op == UnaryEltwiseOperation::Exp)
+ {
+ return UnaryEltwiseLayerFunctions::ExpLayer::validate(input, output);
+ }
+ else
+ {
+ ARM_COMPUTE_ERROR("Unsupported unary element-wise operation!");
+ }
+
+ return Status{};
+}
} // namespace detail
} // namespace backends
} // namespace graph
diff --git a/arm_compute/graph/nodes/EltwiseLayerNode.h b/arm_compute/graph/nodes/EltwiseLayerNode.h
index d619ad2588..9ea5d69ac9 100644
--- a/arm_compute/graph/nodes/EltwiseLayerNode.h
+++ b/arm_compute/graph/nodes/EltwiseLayerNode.h
@@ -63,6 +63,12 @@ public:
*/
ActivationLayerInfo fused_activation() const;
+ /** Returns output quantization info
+ *
+ * @return Output quantization info
+ */
+ QuantizationInfo output_quant_info() const;
+
/** Sets fused activation
*
* @param[in] fused_activation Fused activation to set
@@ -80,6 +86,40 @@ public:
private:
descriptors::EltwiseLayerDescriptor descriptor;
};
+
+/** Unary Eltwise Layer node */
+class UnaryEltwiseLayerNode final : public INode
+{
+public:
+ /** Constructor
+ *
+ * @param[in] descriptor Containing information for the node described in @ref descriptors::EltwiseLayerDescriptor
+ */
+ UnaryEltwiseLayerNode(const descriptors::UnaryEltwiseLayerDescriptor &descriptor);
+ /** Unary eltwise layer descriptor
+ *
+ * @return Unary eltwise layer descriptor which containing information
+ */
+ descriptors::UnaryEltwiseLayerDescriptor eltwise_descriptor() const;
+
+ /** Sets fused activation
+ *
+ * @param[in] fused_activation Fused activation to set
+ */
+ void set_fused_activation(ActivationLayerInfo fused_activation);
+
+ // Inherited overridden methods:
+ NodeType type() const override;
+ bool forward_descriptors() override;
+ TensorDescriptor configure_output(size_t idx) const override;
+ void accept(INodeVisitor &v) override;
+
+ static constexpr NodeType node_type = NodeType::UnaryEltwiseLayer;
+
+private:
+ descriptors::UnaryEltwiseLayerDescriptor descriptor;
+};
+
} // namespace graph
} // namespace arm_compute
#endif /* ARM_COMPUTE_GRAPH_ELTWISE_LAYER_NODE_H */
diff --git a/arm_compute/graph/nodes/SplitLayerNode.h b/arm_compute/graph/nodes/SplitLayerNode.h
index 345260ab84..b5dea7f8c5 100644
--- a/arm_compute/graph/nodes/SplitLayerNode.h
+++ b/arm_compute/graph/nodes/SplitLayerNode.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019 ARM Limited.
+ * Copyright (c) 2018-2020 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -38,10 +38,13 @@ class SplitLayerNode final : public INode
public:
/** Default Constructor
*
- * @param[in] num_splits Number of splits
- * @param[in] axis (Optional) Axis to split on. Supported axis >= 2. Defaults to 0
+ * @param[in] num_splits Number of splits
+ * @param[in] axis (Optional) Axis to split on. Defaults to 0
+ * @param[in] size_splits (Optional) The sizes of each output tensor along the split dimension.
+ * Must sum to the dimension of value along split_dim.
+ * Can contain one -1 indicating that dimension is to be inferred.
*/
- SplitLayerNode(unsigned int num_splits, unsigned int axis = 0);
+ SplitLayerNode(unsigned int num_splits, int axis = 0, std::vector<int> size_splits = std::vector<int>());
/** Computes split layer output descriptor
*
* @param[in] input_descriptor Descriptor of the input tensor
@@ -51,8 +54,8 @@ public:
*
* @return A pair with the descriptor of the split and the starting coordinates
*/
- static std::pair<TensorDescriptor, Coordinates> compute_output_descriptor(const TensorDescriptor &input_descriptor,
- unsigned int num_splits, unsigned int axis, unsigned int idx);
+ std::pair<TensorDescriptor, Coordinates> compute_output_descriptor(const TensorDescriptor &input_descriptor,
+ unsigned int num_splits, int axis, unsigned int idx);
/** Number of splits accessor
*
* @return Number of splits
@@ -72,8 +75,9 @@ public:
void accept(INodeVisitor &v) override;
private:
- unsigned int _num_splits;
- unsigned int _axis;
+ unsigned int _num_splits;
+ int _axis;
+ std::vector<int> _size_splits;
};
} // namespace graph
} // namespace arm_compute