src/armnn/optimizations/SquashEqualSiblings.hpp
src/armnn/optimizations/OptimizeInverseConversions.hpp
src/armnn/optimizations/ConvertFp32NetworkToFp16.hpp
+ src/armnn/optimizations/AddDebug.hpp
third-party/half/half.hpp
)
struct OptimizerOptions
{
- OptimizerOptions() : m_ReduceFp32ToFp16(false) {}
+ OptimizerOptions() :
+ m_ReduceFp32ToFp16(false)
+ , m_Debug(false)
+ {}
- OptimizerOptions(bool reduceFp32ToFp16)
+ OptimizerOptions(bool reduceFp32ToFp16, bool debug)
: m_ReduceFp32ToFp16(reduceFp32ToFp16)
+ , m_Debug(debug)
{
}
// Reduce Fp32 data to Fp16 for faster processing
bool m_ReduceFp32ToFp16;
+
+ // Add debug data for easier troubleshooting
+ bool m_Debug;
};
/// Create an optimized version of the network
Optimizer::Pass(optNetObjPtr->GetGraph(), MakeOptimizations(Fp32NetworkToFp16Converter()));
}
+ // if debug optimization is set, then print out data after each layer
+ if (options.m_Debug)
+ {
+ Optimizer::Pass(optNetObjPtr->GetGraph(), MakeOptimizations(InsertDebugLayer()));
+ }
+
// We know that DeviceSpec should be the only implementation of IDeviceSpec.
const DeviceSpec& spec = *boost::polymorphic_downcast<const DeviceSpec*>(&deviceSpec);
auto const& supportedBackends = spec.GetSupportedBackends();
return convertLayers;
}
+
+std::vector<DebugLayer*> InsertDebugLayerAfter(Graph& graph, Layer& layer)
+{
+ std::vector<DebugLayer*> debugLayers;
+ debugLayers.reserve(layer.GetNumOutputSlots());
+
+ // Change outputs to DataType::Float16
+ for (auto&& outputSlot = layer.BeginOutputSlots(); outputSlot != layer.EndOutputSlots(); ++outputSlot)
+ {
+ // Insert debug layer after the layer
+ const std::string name =
+ std::string("DebugLayerAfter") + layer.GetName();
+
+ const DebugDescriptor descriptor;
+
+ DebugLayer* debugLayer =
+ graph.InsertNewLayer<DebugLayer>(*outputSlot, descriptor, name.c_str());
+
+ // Sets output tensor info for the debug layer.
+ TensorInfo debugInfo = debugLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo();
+
+ debugLayer->GetOutputSlot().SetTensorInfo(debugInfo);
+
+ debugLayers.emplace_back(debugLayer);
+ }
+
+ return debugLayers;
+}
+
} // namespace armnn
std::vector<ConvertFp32ToFp16Layer*> InsertConvertFp32ToFp16LayersAfter(Graph& graph, Layer& layer);
+std::vector<DebugLayer*> InsertDebugLayerAfter(Graph& graph, Layer& layer);
+
} // namespace armnn
--- /dev/null
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include "Optimization.hpp"
+#include "NetworkUtils.hpp"
+
+namespace armnn
+{
+namespace optimizations
+{
+
+class AddDebugImpl
+{
+public:
+
+ void Run(Graph& graph, Layer& layer) const
+ {
+ if (layer.GetType() != LayerType::Debug && layer.GetType() != LayerType::Output)
+ {
+ // if the inputs/outputs of this layer do not have a debug layer
+ // insert the debug layer after them
+ InsertDebugLayerAfter(graph, layer);
+ }
+ }
+
+protected:
+ AddDebugImpl() = default;
+ ~AddDebugImpl() = default;
+};
+
+using InsertDebugLayer = OptimizeForType<Layer, AddDebugImpl>;
+
+} // namespace optimizations
+} // namespace armnn
#include "MovePermuteUp.hpp"
#include "OptimizeInverseConversions.hpp"
#include "ConvertFp32NetworkToFp16.hpp"
+#include "AddDebug.hpp"
&IsLayerOfType<armnn::OutputLayer>));
}
+BOOST_AUTO_TEST_CASE(InsertDebugOptimizationTest)
+{
+ armnn::Graph graph;
+
+ const armnn::TensorInfo info({ 2,2,1,3 }, armnn::DataType::Float32);
+
+ // Create the simple test network
+ auto input = graph.AddLayer<armnn::InputLayer>(0, "input");
+ input->GetOutputSlot().SetTensorInfo(info);
+
+ auto floor = graph.AddLayer<armnn::FloorLayer>("floor");
+ floor->GetOutputSlot().SetTensorInfo(info);
+
+ auto output = graph.AddLayer<armnn::OutputLayer>(1, "output");
+
+ // Connect up the layers
+ input->GetOutputSlot().Connect(floor->GetInputSlot(0));
+ floor->GetOutputSlot().Connect(output->GetInputSlot(0));
+
+ BOOST_TEST(CheckSequence(graph.cbegin(),
+ graph.cend(),
+ &IsLayerOfType<armnn::InputLayer>,
+ &IsLayerOfType<armnn::FloorLayer>,
+ &IsLayerOfType<armnn::OutputLayer>));
+
+ // Run the optimizer
+ armnn::Optimizer::Pass(graph, armnn::MakeOptimizations(InsertDebugLayer()));
+
+ BOOST_TEST(CheckSequence(graph.cbegin(),
+ graph.cend(),
+ &IsLayerOfType<armnn::InputLayer>,
+ &IsLayerOfType<armnn::DebugLayer>,
+ &IsLayerOfType<armnn::FloorLayer>,
+ &IsLayerOfType<armnn::DebugLayer>,
+ &IsLayerOfType<armnn::OutputLayer>));
+}
+
void CreateConvolution2dGraph(Graph &graph, const unsigned int* inputShape,
const unsigned int* weightsShape, const unsigned int* outputShape,
DataLayout dataLayout = DataLayout::NCHW)
#include <reference/RefWorkloadFactory.hpp>
#include <boost/test/unit_test.hpp>
+#include <test/GraphUtils.hpp>
BOOST_AUTO_TEST_SUITE(RefOptimizedNetwork)
BOOST_TEST(ss.str() == expected.str());
}
+BOOST_AUTO_TEST_CASE(DebugTestOnCpuRef)
+{
+ armnn::Network net;
+
+ armnn::ActivationDescriptor activation1Descriptor;
+ activation1Descriptor.m_Function = armnn::ActivationFunction::BoundedReLu;
+ activation1Descriptor.m_A = 1.f;
+ activation1Descriptor.m_B = -1.f;
+
+ // Defines layers.
+ auto input = net.AddInputLayer(0, "InputLayer");
+ auto activation = net.AddActivationLayer(activation1Descriptor, "ActivationLayer");
+ auto output = net.AddOutputLayer(0, "OutputLayer");
+
+ // Connects layers.
+ input->GetOutputSlot(0).Connect(activation->GetInputSlot(0));
+ activation->GetOutputSlot(0).Connect(output->GetInputSlot(0));
+
+ armnn::TensorShape shape({4});
+ armnn::TensorInfo info(shape, armnn::DataType::Float32);
+ input->GetOutputSlot(0).SetTensorInfo(info);
+ activation->GetOutputSlot(0).SetTensorInfo(info);
+
+ armnn::IRuntime::CreationOptions options;
+ armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
+
+ std::vector<armnn::BackendId> backends = {armnn::Compute::CpuRef};
+
+ armnn::OptimizerOptions optimizerOptions;
+ optimizerOptions.m_Debug = true;
+
+ armnn::IOptimizedNetworkPtr optimizedNet = armnn::Optimize(net, backends, runtime->GetDeviceSpec(),
+ optimizerOptions);
+
+ const armnn::Graph& graph = static_cast<armnn::OptimizedNetwork*>(optimizedNet.get())->GetGraph();
+ // Tests that all layers are present in the graph.
+ BOOST_TEST(graph.GetNumLayers() == 5);
+
+ // Tests that the vertices exist and have correct names.
+ BOOST_TEST(GraphHasNamedLayer(graph, "InputLayer"));
+ BOOST_TEST(GraphHasNamedLayer(graph, "DebugLayerAfterInputLayer"));
+ BOOST_TEST(GraphHasNamedLayer(graph, "ActivationLayer"));
+ BOOST_TEST(GraphHasNamedLayer(graph, "DebugLayerAfterActivationLayer"));
+ BOOST_TEST(GraphHasNamedLayer(graph, "OutputLayer"));
+}
+
BOOST_AUTO_TEST_SUITE_END()