From ed99f411d52949720a4d64d91664cd71e46b79d5 Mon Sep 17 00:00:00 2001 From: Gian Marco Iodice Date: Wed, 21 Mar 2018 17:45:31 +0000 Subject: COMPMID-1018 - Add Winograd support in VGG16 and Alexnet examples Change-Id: I4a2deee9e4b2c54ea79d2895cfeca44190133b24 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/125453 Reviewed-by: Pablo Tello Tested-by: Jenkins --- examples/graph_alexnet.cpp | 8 +++++--- examples/graph_vgg16.cpp | 9 ++++++--- src/graph/nodes/ConvolutionLayer.cpp | 22 +++++++++++++--------- src/graph2/backends/CL/CLFunctionsFactory.cpp | 8 +++++++- 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/examples/graph_alexnet.cpp b/examples/graph_alexnet.cpp index a396c7686c..f887f97a12 100644 --- a/examples/graph_alexnet.cpp +++ b/examples/graph_alexnet.cpp @@ -57,8 +57,10 @@ public: const int int_target_hint = argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0; TargetHint target_hint = set_target_hint(int_target_hint); - const bool is_gemm_convolution5x5 = Graph::gpu_target() == arm_compute::GPUTarget::MIDGARD || target_hint == TargetHint::NEON; - ConvolutionMethodHint convolution_5x5_hint = is_gemm_convolution5x5 ? ConvolutionMethodHint::GEMM : ConvolutionMethodHint::DIRECT; + const bool is_gemm_convolution5x5 = Graph::gpu_target() == arm_compute::GPUTarget::MIDGARD || target_hint == TargetHint::NEON; + const bool is_winograd_convolution3x3 = target_hint == TargetHint::OPENCL; + ConvolutionMethodHint convolution_5x5_hint = is_gemm_convolution5x5 ? ConvolutionMethodHint::GEMM : ConvolutionMethodHint::DIRECT; + ConvolutionMethodHint convolution_3x3_hint = is_winograd_convolution3x3 ? ConvolutionMethodHint::WINOGRAD : ConvolutionMethodHint::GEMM; // Parse arguments if(argc < 2) @@ -114,7 +116,7 @@ public: << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)) << NormalizationLayer(NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f)) << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0))) - << ConvolutionMethodHint::GEMM + << convolution_3x3_hint // Layer 3 << ConvolutionLayer( 3U, 3U, 384U, diff --git a/examples/graph_vgg16.cpp b/examples/graph_vgg16.cpp index faaf579047..516b7b18f0 100644 --- a/examples/graph_vgg16.cpp +++ b/examples/graph_vgg16.cpp @@ -71,8 +71,10 @@ public: bool enable_memory_management = true; // Check if we can use GEMM-based convolutions evaluating if the platform has at least 1.8 GB of available memory - const size_t memory_required = 1932735283L; - ConvolutionMethod convolution_hint = convolution_hint_vgg16(memory_required); + const size_t memory_required = 1932735283L; + const bool is_opencl = target_hint == Target::CL; + ConvolutionMethod first_convolution3x3_hint = is_opencl ? ConvolutionMethod::DIRECT : ConvolutionMethod::GEMM; + ConvolutionMethod convolution3x3_hint = is_opencl ? ConvolutionMethod::WINOGRAD : convolution_hint_vgg16(memory_required); // Parse arguments if(argc < 2) @@ -107,7 +109,7 @@ public: } graph << target_hint - << convolution_hint + << first_convolution3x3_hint << InputLayer(TensorDescriptor(TensorShape(224U, 224U, 3U, 1U), DataType::F32), get_input_accessor(image, std::move(preprocessor))) // Layer 1 @@ -117,6 +119,7 @@ public: get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv1_1_b.npy"), PadStrideInfo(1, 1, 1, 1)) << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)) + << convolution3x3_hint // Layer 2 << ConvolutionLayer( 3U, 3U, 64U, diff --git a/src/graph/nodes/ConvolutionLayer.cpp b/src/graph/nodes/ConvolutionLayer.cpp index d8089d804d..5b3a84a4ad 100644 --- a/src/graph/nodes/ConvolutionLayer.cpp +++ b/src/graph/nodes/ConvolutionLayer.cpp @@ -26,6 +26,7 @@ #include "arm_compute/graph/Error.h" #include "arm_compute/runtime/CL/functions/CLConvolutionLayer.h" #include "arm_compute/runtime/CL/functions/CLDirectConvolutionLayer.h" +#include "arm_compute/runtime/CL/functions/CLWinogradConvolutionLayer.h" #include "arm_compute/runtime/IFunction.h" #include "arm_compute/runtime/NEON/functions/NEConvolutionLayer.h" #include "arm_compute/runtime/NEON/functions/NEDirectConvolutionLayer.h" @@ -107,8 +108,14 @@ std::unique_ptr instantiate(arm_comp const WeightsInfo &weights_info, ConvolutionMethodHint conv_method) { - if((conv_method == ConvolutionMethodHint::DIRECT) - && arm_compute::CLDirectConvolutionLayer::validate(input->info(), weights->info(), biases != nullptr ? biases->info() : nullptr, output->info(), conv_info)) // NOLINT + if((conv_method == ConvolutionMethodHint::WINOGRAD) + && arm_compute::CLWinogradConvolutionLayer::validate(input->info(), weights->info(), biases != nullptr ? biases->info() : nullptr, output->info(), conv_info)) // NOLINT + { + ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLWinogradConvolutionLayer"); + return instantiate_direct_function(input, weights, biases, output, conv_info); + } + else if((conv_method == ConvolutionMethodHint::DIRECT) + && arm_compute::CLDirectConvolutionLayer::validate(input->info(), weights->info(), biases != nullptr ? biases->info() : nullptr, output->info(), conv_info)) // NOLINT { ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLDirectConvolutionLayer"); return instantiate_direct_function(input, weights, biases, output, conv_info); @@ -159,10 +166,7 @@ class GroupedConvolutionFunction final : public arm_compute::IFunction { public: /** Default Constructor */ - GroupedConvolutionFunction() - : _convolutions() - { - } + GroupedConvolutionFunction() = default; /** Default Destructor */ ~GroupedConvolutionFunction() final = default; /** Prevent instances from being copy constructed */ @@ -177,12 +181,12 @@ public: * * @param convolution Convolution function to add */ - void add_convolution_function(std::unique_ptr convolution) + void add_convolution_function(std::unique_ptr convolution) // NOLINT { _convolutions.emplace_back(std::move(convolution)); } - // Inherited methods overriden: + // Inherited methods overridden: void run() override { for(auto &c : _convolutions) @@ -192,7 +196,7 @@ public: } private: - std::vector> _convolutions; + std::vector> _convolutions{}; }; std::unique_ptr ConvolutionLayer::instantiate_node(GraphContext &ctx, ITensorObject *input, ITensorObject *output) diff --git a/src/graph2/backends/CL/CLFunctionsFactory.cpp b/src/graph2/backends/CL/CLFunctionsFactory.cpp index bba0cce025..5a51b19e18 100644 --- a/src/graph2/backends/CL/CLFunctionsFactory.cpp +++ b/src/graph2/backends/CL/CLFunctionsFactory.cpp @@ -165,7 +165,13 @@ std::unique_ptr create_convolution_layer(ConvolutionLayerNode &node, std::shared_ptr mm = get_memory_manager(ctx, Target::CL); std::unique_ptr func; std::string func_name; - if(conv_algorithm == ConvolutionMethod::DIRECT) + + if(conv_algorithm == ConvolutionMethod::WINOGRAD) + { + std::tie(func, func_name) = create_named_function( + std::string("CLWinogradConvolutionLayer"), input, weights, biases, output, conv_info); + } + else if(conv_algorithm == ConvolutionMethod::DIRECT) { std::tie(func, func_name) = create_named_function( std::string("CLDirectConvolutionLayer"), input, weights, biases, output, conv_info); -- cgit v1.2.1