blob: 79184416cd2407a6a5929f32f216c0bec088582d [file] [log] [blame]
Keith Davis02356de2019-08-26 18:28:17 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "ProfilingService.hpp"
7
Matteo Martincigha84edee2019-10-02 12:50:57 +01008#include <boost/log/trivial.hpp>
9#include <boost/format.hpp>
10
Keith Davis02356de2019-08-26 18:28:17 +010011namespace armnn
12{
13
14namespace profiling
15{
16
Matteo Martincigha84edee2019-10-02 12:50:57 +010017void ProfilingService::ResetExternalProfilingOptions(const ExternalProfilingOptions& options,
18 bool resetProfilingService)
Keith Davis02356de2019-08-26 18:28:17 +010019{
Matteo Martincigha84edee2019-10-02 12:50:57 +010020 // Update the profiling options
21 m_Options = options;
Keith Davis02356de2019-08-26 18:28:17 +010022
Matteo Martincigh54fb9572019-10-02 12:50:57 +010023 // Check if the profiling service needs to be reset
Matteo Martincigha84edee2019-10-02 12:50:57 +010024 if (resetProfilingService)
Keith Davis02356de2019-08-26 18:28:17 +010025 {
Matteo Martincigha84edee2019-10-02 12:50:57 +010026 // Reset the profiling service
Matteo Martincigh54fb9572019-10-02 12:50:57 +010027 Reset();
Keith Davis02356de2019-08-26 18:28:17 +010028 }
29}
30
Matteo Martincigh54fb9572019-10-02 12:50:57 +010031void ProfilingService::Update()
Keith Davis02356de2019-08-26 18:28:17 +010032{
Matteo Martincigh54fb9572019-10-02 12:50:57 +010033 if (!m_Options.m_EnableProfiling)
Matteo Martincigha84edee2019-10-02 12:50:57 +010034 {
Matteo Martincigh54fb9572019-10-02 12:50:57 +010035 // Don't run if profiling is disabled
36 return;
Matteo Martincigha84edee2019-10-02 12:50:57 +010037 }
Matteo Martincigh54fb9572019-10-02 12:50:57 +010038
39 ProfilingState currentState = m_StateMachine.GetCurrentState();
40 switch (currentState)
Keith Davis02356de2019-08-26 18:28:17 +010041 {
Matteo Martincigh54fb9572019-10-02 12:50:57 +010042 case ProfilingState::Uninitialised:
43 // Initialize the profiling service
44 Initialize();
45
46 // Move to the next state
47 m_StateMachine.TransitionToState(ProfilingState::NotConnected);
48 break;
49 case ProfilingState::NotConnected:
Matteo Martincighd0613b52019-10-09 16:47:04 +010050 // Stop the command thread (if running)
51 m_CommandHandler.Stop();
52
53 // Stop the send thread (if running)
54 m_SendCounterPacket.Stop(false);
Matteo Martincigh54fb9572019-10-02 12:50:57 +010055
Matteo Martincighe8485382019-10-10 14:08:21 +010056 // Stop the periodic counter capture thread (if running)
57 m_PeriodicCounterCapture.Stop();
58
Matteo Martincigh54fb9572019-10-02 12:50:57 +010059 // Reset any existing profiling connection
60 m_ProfilingConnection.reset();
61
Sadik Armaganbd9e2c52019-09-26 23:13:31 +010062 try
Keith Davis02356de2019-08-26 18:28:17 +010063 {
Matteo Martincigh54fb9572019-10-02 12:50:57 +010064 // Setup the profiling connection
Matteo Martincighd0613b52019-10-09 16:47:04 +010065 BOOST_ASSERT(m_ProfilingConnectionFactory);
Matteo Martincigh54fb9572019-10-02 12:50:57 +010066 m_ProfilingConnection = m_ProfilingConnectionFactory->GetProfilingConnection(m_Options);
Keith Davis02356de2019-08-26 18:28:17 +010067 }
Matteo Martincigh54fb9572019-10-02 12:50:57 +010068 catch (const Exception& e)
Sadik Armaganbd9e2c52019-09-26 23:13:31 +010069 {
Matteo Martincigh54fb9572019-10-02 12:50:57 +010070 BOOST_LOG_TRIVIAL(warning) << "An error has occurred when creating the profiling connection: "
Matteo Martincighd0613b52019-10-09 16:47:04 +010071 << e.what() << std::endl;
Sadik Armaganbd9e2c52019-09-26 23:13:31 +010072 }
Matteo Martincigh54fb9572019-10-02 12:50:57 +010073
74 // Move to the next state
75 m_StateMachine.TransitionToState(m_ProfilingConnection
76 ? ProfilingState::WaitingForAck // Profiling connection obtained, wait for ack
77 : ProfilingState::NotConnected); // Profiling connection failed, stay in the
78 // "NotConnected" state
79 break;
80 case ProfilingState::WaitingForAck:
81 BOOST_ASSERT(m_ProfilingConnection);
82
83 // Start the command thread
84 m_CommandHandler.Start(*m_ProfilingConnection);
85
86 // Start the send thread, while in "WaitingForAck" state it'll send out a "Stream MetaData" packet waiting for
87 // a valid "Connection Acknowledged" packet confirming the connection
88 m_SendCounterPacket.Start(*m_ProfilingConnection);
89
90 // The connection acknowledged command handler will automatically transition the state to "Active" once a
91 // valid "Connection Acknowledged" packet has been received
92
93 break;
94 case ProfilingState::Active:
95
Matteo Martincighe8485382019-10-10 14:08:21 +010096 // The period counter capture thread is started by the Periodic Counter Selection command handler upon
97 // request by an external profiling service
98
Matteo Martincigh54fb9572019-10-02 12:50:57 +010099 break;
100 default:
101 throw RuntimeException(boost::str(boost::format("Unknown profiling service state: %1")
102 % static_cast<int>(currentState)));
Sadik Armaganbd9e2c52019-09-26 23:13:31 +0100103 }
Keith Davis02356de2019-08-26 18:28:17 +0100104}
105
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100106const ICounterDirectory& ProfilingService::GetCounterDirectory() const
107{
108 return m_CounterDirectory;
109}
110
Matteo Martincigha84edee2019-10-02 12:50:57 +0100111ProfilingState ProfilingService::GetCurrentState() const
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100112{
Matteo Martincigha84edee2019-10-02 12:50:57 +0100113 return m_StateMachine.GetCurrentState();
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100114}
115
116uint16_t ProfilingService::GetCounterCount() const
117{
118 return m_CounterDirectory.GetCounterCount();
119}
120
Matteo Martincighe8485382019-10-10 14:08:21 +0100121bool ProfilingService::IsCounterRegistered(uint16_t counterUid) const
122{
123 return counterUid < m_CounterIndex.size();
124}
125
Matteo Martincigha84edee2019-10-02 12:50:57 +0100126uint32_t ProfilingService::GetCounterValue(uint16_t counterUid) const
Keith Davis02356de2019-08-26 18:28:17 +0100127{
Matteo Martincighe8485382019-10-10 14:08:21 +0100128 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100129 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
130 BOOST_ASSERT(counterValuePtr);
131 return counterValuePtr->load(std::memory_order::memory_order_relaxed);
Keith Davis02356de2019-08-26 18:28:17 +0100132}
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100133
Matteo Martincigha84edee2019-10-02 12:50:57 +0100134void ProfilingService::SetCounterValue(uint16_t counterUid, uint32_t value)
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100135{
Matteo Martincighe8485382019-10-10 14:08:21 +0100136 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100137 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
138 BOOST_ASSERT(counterValuePtr);
139 counterValuePtr->store(value, std::memory_order::memory_order_relaxed);
140}
141
142uint32_t ProfilingService::AddCounterValue(uint16_t counterUid, uint32_t value)
143{
Matteo Martincighe8485382019-10-10 14:08:21 +0100144 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100145 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
146 BOOST_ASSERT(counterValuePtr);
147 return counterValuePtr->fetch_add(value, std::memory_order::memory_order_relaxed);
148}
149
150uint32_t ProfilingService::SubtractCounterValue(uint16_t counterUid, uint32_t value)
151{
Matteo Martincighe8485382019-10-10 14:08:21 +0100152 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100153 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
154 BOOST_ASSERT(counterValuePtr);
155 return counterValuePtr->fetch_sub(value, std::memory_order::memory_order_relaxed);
156}
157
158uint32_t ProfilingService::IncrementCounterValue(uint16_t counterUid)
159{
Matteo Martincighe8485382019-10-10 14:08:21 +0100160 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100161 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
162 BOOST_ASSERT(counterValuePtr);
163 return counterValuePtr->operator++(std::memory_order::memory_order_relaxed);
164}
165
166uint32_t ProfilingService::DecrementCounterValue(uint16_t counterUid)
167{
Matteo Martincighe8485382019-10-10 14:08:21 +0100168 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100169 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
170 BOOST_ASSERT(counterValuePtr);
171 return counterValuePtr->operator--(std::memory_order::memory_order_relaxed);
172}
173
174void ProfilingService::Initialize()
175{
Matteo Martincigha84edee2019-10-02 12:50:57 +0100176 // Register a category for the basic runtime counters
177 if (!m_CounterDirectory.IsCategoryRegistered("ArmNN_Runtime"))
178 {
179 m_CounterDirectory.RegisterCategory("ArmNN_Runtime");
180 }
181
182 // Register a counter for the number of loaded networks
183 if (!m_CounterDirectory.IsCounterRegistered("Loaded networks"))
184 {
185 const Counter* loadedNetworksCounter =
186 m_CounterDirectory.RegisterCounter("ArmNN_Runtime",
187 0,
188 0,
189 1.f,
190 "Loaded networks",
191 "The number of networks loaded at runtime",
192 std::string("networks"));
193 BOOST_ASSERT(loadedNetworksCounter);
194 InitializeCounterValue(loadedNetworksCounter->m_Uid);
195 }
196
197 // Register a counter for the number of registered backends
198 if (!m_CounterDirectory.IsCounterRegistered("Registered backends"))
199 {
200 const Counter* registeredBackendsCounter =
201 m_CounterDirectory.RegisterCounter("ArmNN_Runtime",
202 0,
203 0,
204 1.f,
205 "Registered backends",
206 "The number of registered backends",
207 std::string("backends"));
208 BOOST_ASSERT(registeredBackendsCounter);
209 InitializeCounterValue(registeredBackendsCounter->m_Uid);
210 }
211
212 // Register a counter for the number of inferences run
213 if (!m_CounterDirectory.IsCounterRegistered("Inferences run"))
214 {
215 const Counter* inferencesRunCounter =
216 m_CounterDirectory.RegisterCounter("ArmNN_Runtime",
217 0,
218 0,
219 1.f,
220 "Inferences run",
221 "The number of inferences run",
222 std::string("inferences"));
223 BOOST_ASSERT(inferencesRunCounter);
224 InitializeCounterValue(inferencesRunCounter->m_Uid);
225 }
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100226}
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100227
Matteo Martincigha84edee2019-10-02 12:50:57 +0100228void ProfilingService::InitializeCounterValue(uint16_t counterUid)
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100229{
Matteo Martincigha84edee2019-10-02 12:50:57 +0100230 // Increase the size of the counter index if necessary
231 if (counterUid >= m_CounterIndex.size())
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100232 {
Matteo Martincigha84edee2019-10-02 12:50:57 +0100233 m_CounterIndex.resize(boost::numeric_cast<size_t>(counterUid) + 1);
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100234 }
Matteo Martincigha84edee2019-10-02 12:50:57 +0100235
236 // Create a new atomic counter and add it to the list
237 m_CounterValues.emplace_back(0);
238
239 // Register the new counter to the counter index for quick access
240 std::atomic<uint32_t>* counterValuePtr = &(m_CounterValues.back());
241 m_CounterIndex.at(counterUid) = counterValuePtr;
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100242}
243
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100244void ProfilingService::Reset()
245{
246 // Reset the profiling service
Matteo Martincighd0613b52019-10-09 16:47:04 +0100247
248 // The order in which we reset/stop the components is not trivial!
249
250 // First stop the threads (Command Handler first)...
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100251 m_CommandHandler.Stop();
252 m_SendCounterPacket.Stop(false);
Matteo Martincighe8485382019-10-10 14:08:21 +0100253 m_PeriodicCounterCapture.Stop();
Matteo Martincighd0613b52019-10-09 16:47:04 +0100254
255 // ...then destroy the profiling connection...
256 m_ProfilingConnection.reset();
257
258 // ...then delete all the counter data and configuration...
259 m_CounterIndex.clear();
260 m_CounterValues.clear();
261 m_CounterDirectory.Clear();
262
263 // ...finally reset the profiling state machine
264 m_StateMachine.Reset();
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100265}
266
Matteo Martincighe8485382019-10-10 14:08:21 +0100267inline void ProfilingService::CheckCounterUid(uint16_t counterUid) const
268{
269 if (!IsCounterRegistered(counterUid))
270 {
271 throw InvalidArgumentException(boost::str(boost::format("Counter UID %1% is not registered") % counterUid));
272 }
273}
274
Keith Davis02356de2019-08-26 18:28:17 +0100275} // namespace profiling
276
Matteo Martincigha84edee2019-10-02 12:50:57 +0100277} // namespace armnn