aboutsummaryrefslogtreecommitdiff
path: root/src/armnn/NetworkUtils.cpp
blob: 735a6244d52ebc9b13172ab8b1c3166f154d7ffa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include "NetworkUtils.hpp"

#include "SubGraphSelector.hpp"

#include <armnn/Exceptions.hpp>

#include <backendsCommon/BackendRegistry.hpp>

namespace armnn
{

std::vector<ConvertFp16ToFp32Layer*> InsertConvertFp16ToFp32LayersBefore(Graph& graph, Layer& layer)
{
    std::vector<ConvertFp16ToFp32Layer*> convertLayers;
    convertLayers.reserve(layer.GetNumInputSlots());

    for (auto&& inputSlot = layer.BeginInputSlots(); inputSlot != layer.EndInputSlots(); ++inputSlot)
    {
        // Insert FP16 to FP32 converter layer before the layer
        const std::string name =
            std::string("convert_fp16_to_fp32-" + std::to_string(inputSlot->GetSlotIndex()) + "-") + layer.GetName();
        ConvertFp16ToFp32Layer* convertLayer =
            graph.InsertNewLayer<ConvertFp16ToFp32Layer>(*inputSlot, name.c_str());

        // Sets output tensor info for the convert layer
        TensorInfo convertInfo = convertLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo();
        convertInfo.SetDataType(DataType::Float32);

        convertLayer->GetOutputSlot().SetTensorInfo(convertInfo);

        convertLayers.emplace_back(convertLayer);
    }

    // Sets the output tensor info for the unsupported layer
    auto UpdateTensorInfo = [](auto& outputSlot)
    {
        // Copy original tensor info and change data type to FP32
        TensorInfo newTensorInfo = outputSlot.GetTensorInfo();
        newTensorInfo.SetDataType(DataType::Float32);

        outputSlot.SetTensorInfo(newTensorInfo);
    };

    std::for_each(layer.BeginOutputSlots(), layer.EndOutputSlots(), UpdateTensorInfo);

    return convertLayers;
}

std::vector<ConvertFp32ToFp16Layer*> InsertConvertFp32ToFp16LayersAfter(Graph& graph, Layer& layer)
{
    std::vector<ConvertFp32ToFp16Layer*> convertLayers;
    convertLayers.reserve(layer.GetNumOutputSlots());

    int index = 0;
    // Change outputs to DataType::Float16
    for (auto&& outputSlot = layer.BeginOutputSlots(); outputSlot != layer.EndOutputSlots(); ++outputSlot)
    {
        BOOST_ASSERT(outputSlot->GetTensorInfo().GetDataType() == DataType::Float32);

        // Insert FP32 to FP16 converter layer after the layer
        const std::string name =
            std::string("convert_fp32_to_fp16-" + std::to_string(index++) + "-") + layer.GetName();
        ConvertFp32ToFp16Layer* convertLayer =
            graph.InsertNewLayer<ConvertFp32ToFp16Layer>(*outputSlot, name.c_str());

        // Sets output tensor info for the convert layer.
        TensorInfo convertInfo = convertLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo();
        convertInfo.SetDataType(DataType::Float16);

        convertLayer->GetOutputSlot().SetTensorInfo(convertInfo);

        convertLayers.emplace_back(convertLayer);
    }

    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);

        // NOTE: It is OK to do this because DebugLayer is only supported on CpuRef
        debugLayer->SetBackendId(Compute::CpuRef);

        debugLayers.emplace_back(debugLayer);
    }

    return debugLayers;
}

PreCompiledLayer* CreatePreCompiledLayer(Graph& graph,
                                         const SubGraph& subGraph,
                                         unsigned int subGraphIndex,
                                         const IBackendInternalUniquePtr& backendObjPtr)
{
    BOOST_ASSERT(backendObjPtr);

    IBackendInternal::ISubGraphConverterPtr converter =
            backendObjPtr->CreateSubGraphConverter(std::make_shared<SubGraph>(subGraph));
    if (!converter)
    {
        return nullptr;
    }

    try
    {
        // Attempt to convert and compile sub-graph
        auto preCompiledObject = converter->GetOutput();
    }
    catch (std::exception&)
    {
        return nullptr;
    }

    // Create pre-compiled layer
    std::string name = "pre-compiled" + std::to_string(subGraphIndex);
    PreCompiledLayer* preCompiledLayer = graph.AddLayer<PreCompiledLayer>(
        PreCompiledDescriptor(subGraph.GetNumInputSlots(), subGraph.GetNumOutputSlots()), name.c_str());

    // Copy output tensor infos from sub-graph
    for (unsigned int i = 0u; i < subGraph.GetNumOutputSlots(); i++)
    {
        preCompiledLayer->GetOutputSlot(i).SetTensorInfo(subGraph.GetOutputSlot(i)->GetTensorInfo());
    }

    // Assign pre-compiled object to layer
    preCompiledLayer->SetPreCompiledObject(converter->GetOutput());

    // Set the backend-id for the pre-compiled layer
    BackendId backendId = backendObjPtr->GetId();
    preCompiledLayer->SetBackendId(backendId);

    return preCompiledLayer;
}

} // namespace armnn