blob: b5474db294b797d4efe4f2523905d9025cbfd93d [file] [log] [blame]
Laurent Carlier749294b2020-06-01 09:03:17 +01001//
Jim Flynn6398a982020-05-27 17:05:21 +01002// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
5#pragma once
6
David Beckb4540be2018-09-24 13:18:27 +01007#include <armnn/Tensor.hpp>
8#include <armnn/Types.hpp>
9
telsoa014fcda012018-03-09 14:13:49 +000010#include "Network.hpp"
11#include "LayerFwd.hpp"
telsoa01c577f2c2018-08-31 09:22:23 +010012#include "Profiling.hpp"
David Beckb4540be2018-09-24 13:18:27 +010013
Matteo Martincighe5b8eb92019-11-28 15:45:42 +000014#include <armnn/backends/IBackendInternal.hpp>
Derek Lamberti84da38b2019-06-13 11:40:08 +010015#include <backendsCommon/TensorHandleFactoryRegistry.hpp>
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000016#include <backendsCommon/Workload.hpp>
17#include <backendsCommon/WorkloadFactory.hpp>
Sadik Armagan3184c902020-03-18 10:57:30 +000018#include <ProfilingService.hpp>
David Monahan6198fe02019-12-02 08:35:43 +000019#include <TimelineUtilityMethods.hpp>
telsoa014fcda012018-03-09 14:13:49 +000020
Derek Lamberti03614f62018-10-02 15:52:46 +010021#include <mutex>
Keith Davise813d672021-04-22 10:10:34 +010022#include <condition_variable>
David Beck29c75de2018-10-23 13:35:58 +010023#include <unordered_map>
Derek Lamberti03614f62018-10-02 15:52:46 +010024
telsoa014fcda012018-03-09 14:13:49 +000025namespace cl
26{
Keith Davise813d672021-04-22 10:10:34 +010027class Context;
28class CommandQueue;
29class Device;
telsoa014fcda012018-03-09 14:13:49 +000030}
31
32namespace armnn
33{
34
telsoa014fcda012018-03-09 14:13:49 +000035class LoadedNetwork
36{
37public:
Keith Davise813d672021-04-22 10:10:34 +010038 using WorkloadQueue = std::vector<std::unique_ptr<IWorkload>>;
39
40 using ExecutionTuple = std::tuple<InputTensors,
41 OutputTensors,
42 std::shared_ptr<IAsyncExecutionCallback>>;
43
44 using ExecutionQueue = std::queue<std::shared_ptr<ExecutionTuple>>;
45
46 ~LoadedNetwork()
47 {
48 FreeWorkingMemory();
49 TerminateThreadPool();
50 }
Derek Lamberti03614f62018-10-02 15:52:46 +010051
Mike Kelly55a8ffd2021-04-07 20:10:49 +010052 /// Create a new unique WorkingMemHandle object. Create multiple handles if you wish to have
53 /// overlapped Execution by calling this function from different threads.
54 std::unique_ptr<IWorkingMemHandle> CreateWorkingMemHandle(NetworkId networkId);
55
telsoa014fcda012018-03-09 14:13:49 +000056 TensorInfo GetInputTensorInfo(LayerBindingId layerId) const;
57 TensorInfo GetOutputTensorInfo(LayerBindingId layerId) const;
58
Keith Davise813d672021-04-22 10:10:34 +010059 /// Single thread execution of the loaded network
surmeh013537c2c2018-05-18 16:31:43 +010060 Status EnqueueWorkload(const InputTensors& inputTensors, const OutputTensors& outputTensors);
telsoa014fcda012018-03-09 14:13:49 +000061
Keith Davise813d672021-04-22 10:10:34 +010062 /// Thread safe execution of the loaded network
Mike Kelly55a8ffd2021-04-07 20:10:49 +010063 Status Execute(const InputTensors& inputTensors,
64 const OutputTensors& outputTensors,
65 IWorkingMemHandle& workingMemHandle);
66
Keith Davise813d672021-04-22 10:10:34 +010067 /// Schedule an asynchronous execution on the loaded network
68 void Schedule(const InputTensors& inputTensors,
69 const OutputTensors& outputTensors,
70 const QosExecPriority priority,
71 std::shared_ptr<IAsyncExecutionCallback> cb);
72
Francis Murtagh3d2b4b22021-02-15 18:23:17 +000073 static std::unique_ptr<LoadedNetwork> MakeLoadedNetwork(std::unique_ptr<IOptimizedNetwork> net,
Keith Davise813d672021-04-22 10:10:34 +010074 std::string& errorMessage,
Sadik Armagan3184c902020-03-18 10:57:30 +000075 const INetworkProperties& networkProperties,
Keith Davise813d672021-04-22 10:10:34 +010076 profiling::ProfilingService& profilingService,
77 const NetworkId networkIdOut);
telsoa01c577f2c2018-08-31 09:22:23 +010078
79 // NOTE we return by reference as the purpose of this method is only to provide
80 // access to the private m_Profiler and in theory we should not need to increment
81 // the shared_ptr's reference counter
Francis Murtagh33199c22021-02-15 10:11:28 +000082 const std::shared_ptr<IProfiler>& GetProfiler() const { return m_Profiler; }
telsoa014fcda012018-03-09 14:13:49 +000083
Derek Lamberti03614f62018-10-02 15:52:46 +010084 void FreeWorkingMemory();
85
Nattapat Chaimanowong6e948202019-03-22 14:01:46 +000086 void RegisterDebugCallback(const DebugCallbackFunction& func);
87
Keith Davis33ed2212020-03-30 10:43:41 +010088 void SendNetworkStructure();
89
Mike Kelly55a8ffd2021-04-07 20:10:49 +010090 bool IsAsyncEnabled()
91 {
92 return m_NetworkProperties.m_AsyncEnabled;
93 }
94
Jim Flynnf7713212020-07-14 09:50:59 +010095 profiling::ProfilingGuid GetNetworkGuid();
96
telsoa014fcda012018-03-09 14:13:49 +000097private:
Finn Williams01097942021-04-26 12:06:34 +010098 using WorkloadFactoryWithMemoryManager =
99 std::pair<IBackendInternal::IWorkloadFactoryPtr, IBackendInternal::IMemoryManagerSharedPtr>;
100
101 using WorkloadFactoryMap = std::unordered_map<BackendId, WorkloadFactoryWithMemoryManager>;
102
Derek Lambertia08d29b2020-06-19 14:33:05 +0100103 void AllocateWorkingMemory(std::lock_guard<std::mutex>& lock);
Finn Williams01097942021-04-26 12:06:34 +0100104 void AllocateAndExecuteConstantWorkloads();
105
106 std::unordered_map<LayerGuid, ITensorHandle* > m_ConstantTensorHandles;
107 std::unordered_map<LayerGuid, std::unique_ptr<IWorkload> > m_ConstantWorkloads;
Matthew Bentham2a326b52019-03-19 10:11:01 +0000108
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000109 LoadedNetwork(std::unique_ptr<IOptimizedNetwork> net,
Sadik Armagan3184c902020-03-18 10:57:30 +0000110 const INetworkProperties& networkProperties,
Keith Davise813d672021-04-22 10:10:34 +0100111 profiling::ProfilingService& profilingService,
112 const NetworkId networkIdOut);
telsoa014fcda012018-03-09 14:13:49 +0000113
surmeh013537c2c2018-05-18 16:31:43 +0100114 void EnqueueInput(const BindableLayer& layer, ITensorHandle* tensorHandle, const TensorInfo& tensorInfo);
telsoa014fcda012018-03-09 14:13:49 +0000115
surmeh013537c2c2018-05-18 16:31:43 +0100116 void EnqueueOutput(const BindableLayer& layer, ITensorHandle* tensorHandle, const TensorInfo& tensorInfo);
telsoa014fcda012018-03-09 14:13:49 +0000117
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100118 void EnqueueInput(const BindableLayer& layer, const ConstTensor& inputTensor, WorkingMemHandle& handle);
119
120 void EnqueueOutput(const BindableLayer& layer, const Tensor& outputTensor, WorkingMemHandle& handle);
121
Keith Davise813d672021-04-22 10:10:34 +0100122 void ProcessExecPriorities(std::unique_ptr<IWorkingMemHandle> workingMemHandle);
123
David Monahan6198fe02019-12-02 08:35:43 +0000124 bool Execute(std::unique_ptr<profiling::TimelineUtilityMethods>& timelineUtils,
125 profiling::ProfilingGuid inferenceGuid);
126
Keith Davise813d672021-04-22 10:10:34 +0100127 void CreateThreadPool(std::size_t numThreads);
128
129 void TerminateThreadPool() noexcept;
130
surmeh013537c2c2018-05-18 16:31:43 +0100131 const IWorkloadFactory& GetWorkloadFactory(const Layer& layer) const;
132
David Beck29c75de2018-10-23 13:35:58 +0100133 using BackendPtrMap = std::unordered_map<BackendId, IBackendInternalUniquePtr>;
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000134
David Beck29c75de2018-10-23 13:35:58 +0100135 BackendPtrMap m_Backends;
136 WorkloadFactoryMap m_WorkloadFactories;
telsoa014fcda012018-03-09 14:13:49 +0000137
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000138 std::unique_ptr<IOptimizedNetwork> m_OptimizedNetwork;
Keith Davise813d672021-04-22 10:10:34 +0100139 std::shared_ptr<IProfiler> m_Profiler;
140
141 WorkloadQueue m_InputQueue;
142 WorkloadQueue m_WorkloadQueue;
143 WorkloadQueue m_OutputQueue;
Derek Lamberti03614f62018-10-02 15:52:46 +0100144
Derek Lamberti03614f62018-10-02 15:52:46 +0100145 mutable std::mutex m_WorkingMemMutex;
Derek Lamberti03614f62018-10-02 15:52:46 +0100146
Keith Davise813d672021-04-22 10:10:34 +0100147 bool m_IsWorkingMemAllocated = false;
148
149 std::vector<std::unique_ptr<std::thread>> m_Threads;
150 std::stack<IWorkingMemHandle> m_WorkingMemHandles;
151
152 ExecutionQueue m_HighPriorityQueue;
153 ExecutionQueue m_MediumPriorityQueue;
154 ExecutionQueue m_LowPriorityQueue;
155
156 // Condition Variables require mutex which will guard the shared state.
157 // Has an event happened? Stop signal for example
158 std::condition_variable m_ThreadPoolEvent;
159 std::mutex m_ThreadPoolMutex;
160
161 // The shared state for conditional variable
162 bool m_TerminatePool = false;
163
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100164 INetworkProperties m_NetworkProperties;
Derek Lamberti84da38b2019-06-13 11:40:08 +0100165
Keith Davise813d672021-04-22 10:10:34 +0100166 const NetworkId m_NetworkId;
167
Derek Lamberti84da38b2019-06-13 11:40:08 +0100168 TensorHandleFactoryRegistry m_TensorHandleFactoryRegistry;
Sadik Armagan3184c902020-03-18 10:57:30 +0000169
Keith Davise813d672021-04-22 10:10:34 +0100170 profiling::ProfilingService& m_ProfilingService;
telsoa014fcda012018-03-09 14:13:49 +0000171};
172
173}