From bb54e4e40b7b08c509e234cd91ebd3087af66c23 Mon Sep 17 00:00:00 2001 From: Giorgio Arena Date: Thu, 5 Apr 2018 17:20:34 +0100 Subject: COMPMID-797 Integrate Mobilenet QASYMM8 with new graph. Change-Id: I4df63ec2f4eb27a8a6eec2bea27741bf8dec6910 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/126966 Tested-by: Jenkins Reviewed-by: Anthony Barbier --- src/graph/GraphBuilder.cpp | 24 +++++++++++++++---- src/graph/backends/CL/CLDeviceBackend.cpp | 2 +- src/graph/backends/CL/CLFunctionsFactory.cpp | 32 +++++++++++++++++++------- src/graph/backends/GLES/GCDeviceBackend.cpp | 2 +- src/graph/backends/GLES/GCFunctionsFactory.cpp | 32 +++++++++++++++++++------- src/graph/backends/NEON/NEDeviceBackend.cpp | 2 +- src/graph/backends/NEON/NEFunctionFactory.cpp | 32 +++++++++++++++++++------- src/graph/nodes/ConvolutionLayerNode.cpp | 10 ++++++-- src/graph/nodes/SoftmaxLayerNode.cpp | 5 +++- 9 files changed, 106 insertions(+), 35 deletions(-) (limited to 'src/graph') diff --git a/src/graph/GraphBuilder.cpp b/src/graph/GraphBuilder.cpp index 0d1bdc3596..4ad34e789c 100644 --- a/src/graph/GraphBuilder.cpp +++ b/src/graph/GraphBuilder.cpp @@ -206,7 +206,9 @@ NodeID GraphBuilder::add_batch_normalization_node(Graph &g, NodeParams params, N NodeID GraphBuilder::add_convolution_node(Graph &g, NodeParams params, NodeIdxPair input, Size2D kernel_spatial_extend, unsigned int depth, PadStrideInfo conv_info, unsigned int num_groups, ConvolutionMethod method, - ITensorAccessorUPtr weights_accessor, ITensorAccessorUPtr bias_accessor) + ITensorAccessorUPtr weights_accessor, ITensorAccessorUPtr bias_accessor, + const QuantizationInfo weights_quant_info, + const QuantizationInfo out_quant_info) { CHECK_NODEIDX_PAIR(input, g); ARM_COMPUTE_ERROR_ON(depth == 0); @@ -220,7 +222,13 @@ NodeID GraphBuilder::add_convolution_node(Graph &g, NodeParams params, NodeIdxPa // Create weights node TensorDescriptor w_desc = input_tensor_desc; w_desc.shape = TensorShape(kernel_spatial_extend.width, kernel_spatial_extend.height, w_desc.shape.z() / num_groups, depth); - NodeID w_nid = add_const_node_with_name(g, params, "Weights", w_desc, std::move(weights_accessor)); + + if(!weights_quant_info.empty()) + { + w_desc.quant_info = weights_quant_info; + } + + NodeID w_nid = add_const_node_with_name(g, params, "Weights", w_desc, std::move(weights_accessor)); // Create bias nodes NodeID b_nid = EmptyNodeID; @@ -234,7 +242,7 @@ NodeID GraphBuilder::add_convolution_node(Graph &g, NodeParams params, NodeIdxPa if(num_groups == 1) { // Create convolution node and connect - NodeID conv_nid = g.add_node(conv_info, method); + NodeID conv_nid = g.add_node(conv_info, method, out_quant_info); g.add_connection(input.node_id, input.index, conv_nid, 0); g.add_connection(w_nid, 0, conv_nid, 1); if(has_bias) @@ -270,7 +278,7 @@ NodeID GraphBuilder::add_depth_concatenate_node(Graph &g, NodeParams params, std NodeID GraphBuilder::add_depthwise_convolution_node(Graph &g, NodeParams params, NodeIdxPair input, Size2D kernel_spatial_extend, PadStrideInfo conv_info, DepthwiseConvolutionMethod method, - ITensorAccessorUPtr weights_accessor, ITensorAccessorUPtr bias_accessor) + ITensorAccessorUPtr weights_accessor, ITensorAccessorUPtr bias_accessor, const QuantizationInfo quant_info) { CHECK_NODEIDX_PAIR(input, g); ARM_COMPUTE_ERROR_ON((kernel_spatial_extend.width == 0) || (kernel_spatial_extend.height == 0)); @@ -283,7 +291,13 @@ NodeID GraphBuilder::add_depthwise_convolution_node(Graph &g, NodeParams params, // Create weights node TensorDescriptor w_desc = input_tensor_desc; w_desc.shape = TensorShape(kernel_spatial_extend.width, kernel_spatial_extend.height, w_desc.shape.z()); - NodeID w_nid = add_const_node_with_name(g, params, "Weights", w_desc, std::move(weights_accessor)); + + if(!quant_info.empty()) + { + w_desc.quant_info = quant_info; + } + + NodeID w_nid = add_const_node_with_name(g, params, "Weights", w_desc, std::move(weights_accessor)); // Create bias nodes NodeID b_nid = EmptyNodeID; diff --git a/src/graph/backends/CL/CLDeviceBackend.cpp b/src/graph/backends/CL/CLDeviceBackend.cpp index f10eb33a98..92cb6936c3 100644 --- a/src/graph/backends/CL/CLDeviceBackend.cpp +++ b/src/graph/backends/CL/CLDeviceBackend.cpp @@ -126,7 +126,7 @@ std::unique_ptr CLDeviceBackend::create_tensor(const Tensor &tens ARM_COMPUTE_ERROR_ON(tensor_desc.target != Target::CL); // Create backend tensor handle - TensorInfo info(tensor_desc.shape, 1, tensor_desc.data_type); + TensorInfo info(tensor_desc.shape, 1, tensor_desc.data_type, tensor_desc.quant_info); auto backend_tensor_handle = support::cpp14::make_unique(info); return std::move(backend_tensor_handle); diff --git a/src/graph/backends/CL/CLFunctionsFactory.cpp b/src/graph/backends/CL/CLFunctionsFactory.cpp index 1b448fefd2..ad73a797e3 100644 --- a/src/graph/backends/CL/CLFunctionsFactory.cpp +++ b/src/graph/backends/CL/CLFunctionsFactory.cpp @@ -154,10 +154,16 @@ std::unique_ptr create_convolution_layer(ConvolutionLayerNode &node, ARM_COMPUTE_ERROR_ON(node.num_outputs() != 1); // Extract IO and info - ICLTensor *input = get_backing_tensor(node.input(0)); - ICLTensor *weights = get_backing_tensor(node.input(1)); - ICLTensor *biases = get_backing_tensor(node.input(2)); - ICLTensor *output = get_backing_tensor(node.output(0)); + ICLTensor *input = get_backing_tensor(node.input(0)); + ICLTensor *weights = get_backing_tensor(node.input(1)); + ICLTensor *biases = get_backing_tensor(node.input(2)); + ICLTensor *output = get_backing_tensor(node.output(0)); + + if(is_data_type_quantized_asymmetric(input->info()->data_type())) + { + biases->info()->set_data_type(DataType::S32); + } + const PadStrideInfo conv_info = node.convolution_info(); const ConvolutionMethod conv_algorithm = node.convolution_method(); @@ -190,6 +196,8 @@ std::unique_ptr create_convolution_layer(ConvolutionLayerNode &node, // Log info ARM_COMPUTE_LOG_GRAPH_INFO("Instantiated " << func_name << " Data Type: " << input->info()->data_type() + << " Input QuantInfo: " << input->info()->quantization_info() + << " Weights QuantInfo: " << weights->info()->quantization_info() << " Input shape: " << input->info()->tensor_shape() << " Weights shape: " << weights->info()->tensor_shape() << " Output shape: " << output->info()->tensor_shape() @@ -251,10 +259,16 @@ std::unique_ptr create_depthwise_convolution_layer(DepthwiseConvoluti ARM_COMPUTE_ERROR_ON(node.num_outputs() != 1); // Extract IO and info - ICLTensor *input = get_backing_tensor(node.input(0)); - ICLTensor *weights = get_backing_tensor(node.input(1)); - ICLTensor *biases = get_backing_tensor(node.input(2)); - ICLTensor *output = get_backing_tensor(node.output(0)); + ICLTensor *input = get_backing_tensor(node.input(0)); + ICLTensor *weights = get_backing_tensor(node.input(1)); + ICLTensor *biases = get_backing_tensor(node.input(2)); + ICLTensor *output = get_backing_tensor(node.output(0)); + + if(is_data_type_quantized_asymmetric(input->info()->data_type())) + { + biases->info()->set_data_type(DataType::S32); + } + const PadStrideInfo conv_info = node.convolution_info(); const DepthwiseConvolutionMethod dwc_algorithm = node.depthwise_convolution_method(); @@ -275,6 +289,8 @@ std::unique_ptr create_depthwise_convolution_layer(DepthwiseConvoluti // Log info ARM_COMPUTE_LOG_GRAPH_INFO("Instantiated " << func_name << " Data Type: " << input->info()->data_type() + << " Input QuantInfo: " << input->info()->quantization_info() + << " Weights QuantInfo: " << weights->info()->quantization_info() << " Input shape: " << input->info()->tensor_shape() << " Weights shape: " << weights->info()->tensor_shape() << " Output shape: " << output->info()->tensor_shape() diff --git a/src/graph/backends/GLES/GCDeviceBackend.cpp b/src/graph/backends/GLES/GCDeviceBackend.cpp index 8cd9994744..a55215f058 100644 --- a/src/graph/backends/GLES/GCDeviceBackend.cpp +++ b/src/graph/backends/GLES/GCDeviceBackend.cpp @@ -87,7 +87,7 @@ std::unique_ptr GCDeviceBackend::create_tensor(const Tensor &tens ARM_COMPUTE_ERROR_ON(tensor_desc.target != Target::GC); // Create backend tensor handle - TensorInfo info(tensor_desc.shape, 1, tensor_desc.data_type); + TensorInfo info(tensor_desc.shape, 1, tensor_desc.data_type, tensor_desc.quant_info); auto backend_tensor_handle = support::cpp14::make_unique(info); return std::move(backend_tensor_handle); diff --git a/src/graph/backends/GLES/GCFunctionsFactory.cpp b/src/graph/backends/GLES/GCFunctionsFactory.cpp index 12e7c042d4..d3c5737e68 100644 --- a/src/graph/backends/GLES/GCFunctionsFactory.cpp +++ b/src/graph/backends/GLES/GCFunctionsFactory.cpp @@ -154,10 +154,16 @@ std::unique_ptr create_convolution_layer(ConvolutionLayerNode &node, ARM_COMPUTE_ERROR_ON(node.num_outputs() != 1); // Extract IO and info - IGCTensor *input = get_backing_tensor(node.input(0)); - IGCTensor *weights = get_backing_tensor(node.input(1)); - IGCTensor *biases = get_backing_tensor(node.input(2)); - IGCTensor *output = get_backing_tensor(node.output(0)); + IGCTensor *input = get_backing_tensor(node.input(0)); + IGCTensor *weights = get_backing_tensor(node.input(1)); + IGCTensor *biases = get_backing_tensor(node.input(2)); + IGCTensor *output = get_backing_tensor(node.output(0)); + + if(is_data_type_quantized_asymmetric(input->info()->data_type())) + { + biases->info()->set_data_type(DataType::S32); + } + const PadStrideInfo conv_info = node.convolution_info(); const ConvolutionMethod conv_algorithm = node.convolution_method(); @@ -180,6 +186,8 @@ std::unique_ptr create_convolution_layer(ConvolutionLayerNode &node, // Log info ARM_COMPUTE_LOG_GRAPH_INFO("Instantiated " << func_name << " Data Type: " << input->info()->data_type() + << " Input QuantInfo: " << input->info()->quantization_info() + << " Weights QuantInfo: " << weights->info()->quantization_info() << " Input shape: " << input->info()->tensor_shape() << " Weights shape: " << weights->info()->tensor_shape() << " Output shape: " << output->info()->tensor_shape() @@ -241,10 +249,16 @@ std::unique_ptr create_depthwise_convolution_layer(DepthwiseConvoluti ARM_COMPUTE_ERROR_ON(node.num_outputs() != 1); // Extract IO and info - IGCTensor *input = get_backing_tensor(node.input(0)); - IGCTensor *weights = get_backing_tensor(node.input(1)); - IGCTensor *biases = get_backing_tensor(node.input(2)); - IGCTensor *output = get_backing_tensor(node.output(0)); + IGCTensor *input = get_backing_tensor(node.input(0)); + IGCTensor *weights = get_backing_tensor(node.input(1)); + IGCTensor *biases = get_backing_tensor(node.input(2)); + IGCTensor *output = get_backing_tensor(node.output(0)); + + if(is_data_type_quantized_asymmetric(input->info()->data_type())) + { + biases->info()->set_data_type(DataType::S32); + } + const PadStrideInfo conv_info = node.convolution_info(); const DepthwiseConvolutionMethod dwc_algorithm = node.depthwise_convolution_method(); @@ -264,6 +278,8 @@ std::unique_ptr create_depthwise_convolution_layer(DepthwiseConvoluti // Log info ARM_COMPUTE_LOG_GRAPH_INFO("Instantiated " << func_name << " Data Type: " << input->info()->data_type() + << " Input QuantInfo: " << input->info()->quantization_info() + << " Weights QuantInfo: " << weights->info()->quantization_info() << " Input shape: " << input->info()->tensor_shape() << " Weights shape: " << weights->info()->tensor_shape() << " Output shape: " << output->info()->tensor_shape() diff --git a/src/graph/backends/NEON/NEDeviceBackend.cpp b/src/graph/backends/NEON/NEDeviceBackend.cpp index aaf05829bb..9123196540 100644 --- a/src/graph/backends/NEON/NEDeviceBackend.cpp +++ b/src/graph/backends/NEON/NEDeviceBackend.cpp @@ -93,7 +93,7 @@ std::unique_ptr NEDeviceBackend::create_tensor(const Tensor &tens ARM_COMPUTE_ERROR_ON(tensor_desc.target != Target::NEON); // Create backend tensor handle - TensorInfo info(tensor_desc.shape, 1, tensor_desc.data_type); + TensorInfo info(tensor_desc.shape, 1, tensor_desc.data_type, tensor_desc.quant_info); auto backend_tensor_handle = support::cpp14::make_unique(info); return std::move(backend_tensor_handle); diff --git a/src/graph/backends/NEON/NEFunctionFactory.cpp b/src/graph/backends/NEON/NEFunctionFactory.cpp index 228af9ca6f..906378c565 100644 --- a/src/graph/backends/NEON/NEFunctionFactory.cpp +++ b/src/graph/backends/NEON/NEFunctionFactory.cpp @@ -140,10 +140,16 @@ std::unique_ptr create_convolution_layer(ConvolutionLayerNode &node, ARM_COMPUTE_ERROR_ON(node.num_outputs() != 1); // Extract IO and info - ITensor *input = get_backing_tensor(node.input(0)); - ITensor *weights = get_backing_tensor(node.input(1)); - ITensor *biases = get_backing_tensor(node.input(2)); - ITensor *output = get_backing_tensor(node.output(0)); + ITensor *input = get_backing_tensor(node.input(0)); + ITensor *weights = get_backing_tensor(node.input(1)); + ITensor *biases = get_backing_tensor(node.input(2)); + ITensor *output = get_backing_tensor(node.output(0)); + + if(is_data_type_quantized_asymmetric(input->info()->data_type())) + { + biases->info()->set_data_type(DataType::S32); + } + const PadStrideInfo conv_info = node.convolution_info(); const ConvolutionMethod conv_algorithm = node.convolution_method(); @@ -175,6 +181,8 @@ std::unique_ptr create_convolution_layer(ConvolutionLayerNode &node, // Log info ARM_COMPUTE_LOG_GRAPH_INFO("Instantiated " << func_name << " Data Type: " << input->info()->data_type() + << " Input QuantInfo: " << input->info()->quantization_info() + << " Weights QuantInfo: " << weights->info()->quantization_info() << " Input shape: " << input->info()->tensor_shape() << " Weights shape: " << weights->info()->tensor_shape() << " Output shape: " << output->info()->tensor_shape() @@ -234,10 +242,16 @@ std::unique_ptr create_depthwise_convolution_layer(DepthwiseConvoluti ARM_COMPUTE_ERROR_ON(node.num_outputs() != 1); // Extract IO and info - ITensor *input = get_backing_tensor(node.input(0)); - ITensor *weights = get_backing_tensor(node.input(1)); - ITensor *biases = get_backing_tensor(node.input(2)); - ITensor *output = get_backing_tensor(node.output(0)); + ITensor *input = get_backing_tensor(node.input(0)); + ITensor *weights = get_backing_tensor(node.input(1)); + ITensor *biases = get_backing_tensor(node.input(2)); + ITensor *output = get_backing_tensor(node.output(0)); + + if(is_data_type_quantized_asymmetric(input->info()->data_type())) + { + biases->info()->set_data_type(DataType::S32); + } + const PadStrideInfo conv_info = node.convolution_info(); const DepthwiseConvolutionMethod dwc_algorithm = node.depthwise_convolution_method(); @@ -258,6 +272,8 @@ std::unique_ptr create_depthwise_convolution_layer(DepthwiseConvoluti // Log info ARM_COMPUTE_LOG_GRAPH_INFO("Instantiated " << func_name << " Data Type: " << input->info()->data_type() + << " Input QuantInfo: " << input->info()->quantization_info() + << " Weights QuantInfo: " << weights->info()->quantization_info() << " Input shape: " << input->info()->tensor_shape() << " Weights shape: " << weights->info()->tensor_shape() << " Output shape: " << output->info()->tensor_shape() diff --git a/src/graph/nodes/ConvolutionLayerNode.cpp b/src/graph/nodes/ConvolutionLayerNode.cpp index 461728487f..eb0c6a1c1a 100644 --- a/src/graph/nodes/ConvolutionLayerNode.cpp +++ b/src/graph/nodes/ConvolutionLayerNode.cpp @@ -31,8 +31,8 @@ namespace arm_compute { namespace graph { -ConvolutionLayerNode::ConvolutionLayerNode(PadStrideInfo info, ConvolutionMethod method) - : _info(std::move(info)), _method(method) +ConvolutionLayerNode::ConvolutionLayerNode(PadStrideInfo info, ConvolutionMethod method, QuantizationInfo out_quant_info) + : _info(std::move(info)), _method(method), _out_quant_info(out_quant_info) { _input_edges.resize(3, EmptyEdgeID); _outputs.resize(1, NullTensorID); @@ -90,6 +90,12 @@ TensorDescriptor ConvolutionLayerNode::configure_output(size_t idx) const TensorDescriptor output_info = src->desc(); TensorShape output_shape = compute_output_shape(src->desc().shape, weights->desc().shape, _info); output_info.shape = output_shape; + + if(!_out_quant_info.empty()) + { + output_info.quant_info = _out_quant_info; + } + return output_info; } diff --git a/src/graph/nodes/SoftmaxLayerNode.cpp b/src/graph/nodes/SoftmaxLayerNode.cpp index 4c21ac6ad0..b6241e6654 100644 --- a/src/graph/nodes/SoftmaxLayerNode.cpp +++ b/src/graph/nodes/SoftmaxLayerNode.cpp @@ -63,7 +63,10 @@ TensorDescriptor SoftmaxLayerNode::configure_output(size_t idx) const const Tensor *src = input(0); ARM_COMPUTE_ERROR_ON(src == nullptr); - return src->desc(); + TensorDescriptor out_desc = src->desc(); + out_desc.quant_info = QuantizationInfo(1.f / 256.f, 0); + + return out_desc; } Status SoftmaxLayerNode::validate() -- cgit v1.2.1