blob: fe407e478a1560078ab8e2093384ae0e51902336 [file] [log] [blame]
Keith Davis02356de2019-08-26 18:28:17 +01001//
Jim Flynn6398a982020-05-27 17:05:21 +01002// Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
Keith Davis02356de2019-08-26 18:28:17 +01003// SPDX-License-Identifier: MIT
4//
5
6#include "ProfilingService.hpp"
7
Keith Davise394bd92019-12-02 15:12:19 +00008#include <armnn/BackendId.hpp>
Derek Lamberti08446972019-11-26 16:38:31 +00009#include <armnn/Logging.hpp>
Matthew Sloyan371b70e2020-09-11 10:14:57 +010010#include <armnn/utility/NumericCast.hpp>
11
Nikhil Raj7dcc6972021-04-30 15:44:24 +010012#include <common/include/ProfilingGuid.hpp>
13
Sadik Armagana97a0be2020-03-03 10:44:56 +000014#include <common/include/SocketConnectionException.hpp>
Derek Lamberti08446972019-11-26 16:38:31 +000015
Jan Eilers156113c2020-09-09 19:11:16 +010016#include <fmt/format.h>
Matteo Martincigha84edee2019-10-02 12:50:57 +010017
Keith Davis02356de2019-08-26 18:28:17 +010018namespace armnn
19{
20
21namespace profiling
22{
23
Sadik Armagan3184c902020-03-18 10:57:30 +000024ProfilingGuidGenerator ProfilingService::m_GuidGenerator;
25
26ProfilingDynamicGuid ProfilingService::GetNextGuid()
27{
28 return m_GuidGenerator.NextGuid();
29}
30
31ProfilingStaticGuid ProfilingService::GetStaticId(const std::string& str)
32{
33 return m_GuidGenerator.GenerateStaticId(str);
34}
35
Jim Flynn6398a982020-05-27 17:05:21 +010036void ProfilingService::ResetGuidGenerator()
37{
38 m_GuidGenerator.Reset();
39}
40
Matteo Martincigha84edee2019-10-02 12:50:57 +010041void ProfilingService::ResetExternalProfilingOptions(const ExternalProfilingOptions& options,
42 bool resetProfilingService)
Keith Davis02356de2019-08-26 18:28:17 +010043{
Matteo Martincigha84edee2019-10-02 12:50:57 +010044 // Update the profiling options
45 m_Options = options;
Keith Davis33ed2212020-03-30 10:43:41 +010046 m_TimelineReporting = options.m_TimelineEnabled;
Finn Williamsd7fcafa2020-04-23 17:55:18 +010047 m_ConnectionAcknowledgedCommandHandler.setTimelineEnabled(options.m_TimelineEnabled);
Keith Davis02356de2019-08-26 18:28:17 +010048
Matteo Martincigh54fb9572019-10-02 12:50:57 +010049 // Check if the profiling service needs to be reset
Matteo Martincigha84edee2019-10-02 12:50:57 +010050 if (resetProfilingService)
Keith Davis02356de2019-08-26 18:28:17 +010051 {
Matteo Martincigha84edee2019-10-02 12:50:57 +010052 // Reset the profiling service
Matteo Martincigh54fb9572019-10-02 12:50:57 +010053 Reset();
Keith Davis02356de2019-08-26 18:28:17 +010054 }
55}
56
Jim Flynn64063552020-02-14 10:18:08 +000057bool ProfilingService::IsProfilingEnabled() const
Keith Davise394bd92019-12-02 15:12:19 +000058{
59 return m_Options.m_EnableProfiling;
60}
61
Jim Flynn672d06e2019-10-15 10:18:11 +010062ProfilingState ProfilingService::ConfigureProfilingService(
63 const ExternalProfilingOptions& options,
64 bool resetProfilingService)
65{
66 ResetExternalProfilingOptions(options, resetProfilingService);
67 ProfilingState currentState = m_StateMachine.GetCurrentState();
68 if (options.m_EnableProfiling)
69 {
70 switch (currentState)
71 {
72 case ProfilingState::Uninitialised:
73 Update(); // should transition to NotConnected
74 Update(); // will either stay in NotConnected because there is no server
75 // or will enter WaitingForAck.
76 currentState = m_StateMachine.GetCurrentState();
77 if (currentState == ProfilingState::WaitingForAck)
78 {
79 Update(); // poke it again to send out the metadata packet
80 }
81 currentState = m_StateMachine.GetCurrentState();
82 return currentState;
83 case ProfilingState::NotConnected:
84 Update(); // will either stay in NotConnected because there is no server
85 // or will enter WaitingForAck
86 currentState = m_StateMachine.GetCurrentState();
87 if (currentState == ProfilingState::WaitingForAck)
88 {
89 Update(); // poke it again to send out the metadata packet
90 }
91 currentState = m_StateMachine.GetCurrentState();
92 return currentState;
93 default:
94 return currentState;
95 }
96 }
97 else
98 {
99 // Make sure profiling is shutdown
100 switch (currentState)
101 {
102 case ProfilingState::Uninitialised:
103 case ProfilingState::NotConnected:
104 return currentState;
105 default:
106 Stop();
107 return m_StateMachine.GetCurrentState();
108 }
109 }
110}
111
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100112void ProfilingService::Update()
Keith Davis02356de2019-08-26 18:28:17 +0100113{
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100114 if (!m_Options.m_EnableProfiling)
Matteo Martincigha84edee2019-10-02 12:50:57 +0100115 {
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100116 // Don't run if profiling is disabled
117 return;
Matteo Martincigha84edee2019-10-02 12:50:57 +0100118 }
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100119
120 ProfilingState currentState = m_StateMachine.GetCurrentState();
121 switch (currentState)
Keith Davis02356de2019-08-26 18:28:17 +0100122 {
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100123 case ProfilingState::Uninitialised:
janeil01811ca552019-12-03 17:01:32 +0000124
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100125 // Initialize the profiling service
126 Initialize();
127
128 // Move to the next state
129 m_StateMachine.TransitionToState(ProfilingState::NotConnected);
130 break;
131 case ProfilingState::NotConnected:
Matteo Martincighd0613b52019-10-09 16:47:04 +0100132 // Stop the command thread (if running)
133 m_CommandHandler.Stop();
134
135 // Stop the send thread (if running)
Sadik Armagan3896b472020-02-10 12:24:15 +0000136 m_SendThread.Stop(false);
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100137
Matteo Martincighe8485382019-10-10 14:08:21 +0100138 // Stop the periodic counter capture thread (if running)
139 m_PeriodicCounterCapture.Stop();
140
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100141 // Reset any existing profiling connection
142 m_ProfilingConnection.reset();
143
Sadik Armaganbd9e2c52019-09-26 23:13:31 +0100144 try
Keith Davis02356de2019-08-26 18:28:17 +0100145 {
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100146 // Setup the profiling connection
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100147 ARMNN_ASSERT(m_ProfilingConnectionFactory);
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100148 m_ProfilingConnection = m_ProfilingConnectionFactory->GetProfilingConnection(m_Options);
Keith Davis02356de2019-08-26 18:28:17 +0100149 }
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100150 catch (const Exception& e)
Sadik Armaganbd9e2c52019-09-26 23:13:31 +0100151 {
Derek Lamberti08446972019-11-26 16:38:31 +0000152 ARMNN_LOG(warning) << "An error has occurred when creating the profiling connection: "
153 << e.what();
Sadik Armaganbd9e2c52019-09-26 23:13:31 +0100154 }
Jim Flynnbbfe6032020-07-20 16:57:44 +0100155 catch (const arm::pipe::SocketConnectionException& e)
Sadik Armagana97a0be2020-03-03 10:44:56 +0000156 {
157 ARMNN_LOG(warning) << "An error has occurred when creating the profiling connection ["
158 << e.what() << "] on socket [" << e.GetSocketFd() << "].";
159 }
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100160
161 // Move to the next state
162 m_StateMachine.TransitionToState(m_ProfilingConnection
163 ? ProfilingState::WaitingForAck // Profiling connection obtained, wait for ack
164 : ProfilingState::NotConnected); // Profiling connection failed, stay in the
165 // "NotConnected" state
166 break;
167 case ProfilingState::WaitingForAck:
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100168 ARMNN_ASSERT(m_ProfilingConnection);
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100169
170 // Start the command thread
171 m_CommandHandler.Start(*m_ProfilingConnection);
172
173 // Start the send thread, while in "WaitingForAck" state it'll send out a "Stream MetaData" packet waiting for
174 // a valid "Connection Acknowledged" packet confirming the connection
Sadik Armagan3896b472020-02-10 12:24:15 +0000175 m_SendThread.Start(*m_ProfilingConnection);
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100176
177 // The connection acknowledged command handler will automatically transition the state to "Active" once a
178 // valid "Connection Acknowledged" packet has been received
179
180 break;
181 case ProfilingState::Active:
182
Matteo Martincighe8485382019-10-10 14:08:21 +0100183 // The period counter capture thread is started by the Periodic Counter Selection command handler upon
184 // request by an external profiling service
185
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100186 break;
187 default:
Jan Eilers156113c2020-09-09 19:11:16 +0100188 throw RuntimeException(fmt::format("Unknown profiling service state: {}",
189 static_cast<int>(currentState)));
Sadik Armaganbd9e2c52019-09-26 23:13:31 +0100190 }
Keith Davis02356de2019-08-26 18:28:17 +0100191}
192
Jim Flynn53e46992019-10-14 12:31:10 +0100193void ProfilingService::Disconnect()
194{
195 ProfilingState currentState = m_StateMachine.GetCurrentState();
196 switch (currentState)
197 {
198 case ProfilingState::Uninitialised:
199 case ProfilingState::NotConnected:
200 case ProfilingState::WaitingForAck:
201 return; // NOP
202 case ProfilingState::Active:
203 // Stop the command thread (if running)
204 Stop();
205
206 break;
207 default:
Jan Eilers156113c2020-09-09 19:11:16 +0100208 throw RuntimeException(fmt::format("Unknown profiling service state: {}",
209 static_cast<int>(currentState)));
Jim Flynn53e46992019-10-14 12:31:10 +0100210 }
211}
212
David Monahanc1536d62020-02-12 15:52:35 +0000213// Store a profiling context returned from a backend that support profiling, and register its counters
214void ProfilingService::AddBackendProfilingContext(const BackendId backendId,
215 std::shared_ptr<armnn::profiling::IBackendProfilingContext> profilingContext)
216{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100217 ARMNN_ASSERT(profilingContext != nullptr);
David Monahanc1536d62020-02-12 15:52:35 +0000218 // Register the backend counters
219 m_MaxGlobalCounterId = profilingContext->RegisterCounters(m_MaxGlobalCounterId);
220 m_BackendProfilingContexts.emplace(backendId, std::move(profilingContext));
221}
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100222const ICounterDirectory& ProfilingService::GetCounterDirectory() const
223{
224 return m_CounterDirectory;
225}
226
Jim Flynn97897022020-02-02 12:52:59 +0000227ICounterRegistry& ProfilingService::GetCounterRegistry()
228{
229 return m_CounterDirectory;
230}
231
Matteo Martincigha84edee2019-10-02 12:50:57 +0100232ProfilingState ProfilingService::GetCurrentState() const
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100233{
Matteo Martincigha84edee2019-10-02 12:50:57 +0100234 return m_StateMachine.GetCurrentState();
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100235}
236
237uint16_t ProfilingService::GetCounterCount() const
238{
239 return m_CounterDirectory.GetCounterCount();
240}
241
Matteo Martincighe8485382019-10-10 14:08:21 +0100242bool ProfilingService::IsCounterRegistered(uint16_t counterUid) const
243{
Finn Williamsb205a332020-05-13 15:04:25 +0100244 return m_CounterDirectory.IsCounterRegistered(counterUid);
Matteo Martincighe8485382019-10-10 14:08:21 +0100245}
246
Finn Williamsf3fcf322020-05-11 14:38:02 +0100247uint32_t ProfilingService::GetAbsoluteCounterValue(uint16_t counterUid) const
Keith Davis02356de2019-08-26 18:28:17 +0100248{
Matteo Martincighe8485382019-10-10 14:08:21 +0100249 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100250 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100251 ARMNN_ASSERT(counterValuePtr);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100252 return counterValuePtr->load(std::memory_order::memory_order_relaxed);
Keith Davis02356de2019-08-26 18:28:17 +0100253}
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100254
Finn Williamsf3fcf322020-05-11 14:38:02 +0100255uint32_t ProfilingService::GetDeltaCounterValue(uint16_t counterUid)
256{
257 CheckCounterUid(counterUid);
258 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
259 ARMNN_ASSERT(counterValuePtr);
260 const uint32_t counterValue = counterValuePtr->load(std::memory_order::memory_order_relaxed);
261 SubtractCounterValue(counterUid, counterValue);
262 return counterValue;
263}
264
Jim Flynn8e0c7a62020-01-30 14:10:55 +0000265const ICounterMappings& ProfilingService::GetCounterMappings() const
266{
267 return m_CounterIdMap;
268}
269
Jim Flynn97897022020-02-02 12:52:59 +0000270IRegisterCounterMapping& ProfilingService::GetCounterMappingRegistry()
Jim Flynn8e0c7a62020-01-30 14:10:55 +0000271{
272 return m_CounterIdMap;
273}
274
James Conroy2dcd3fe2020-02-06 18:34:52 +0000275CaptureData ProfilingService::GetCaptureData()
276{
277 return m_Holder.GetCaptureData();
278}
279
Finn Williams032bc742020-02-12 11:02:34 +0000280void ProfilingService::SetCaptureData(uint32_t capturePeriod,
281 const std::vector<uint16_t>& counterIds,
282 const std::set<BackendId>& activeBackends)
James Conroy2dcd3fe2020-02-06 18:34:52 +0000283{
Finn Williams032bc742020-02-12 11:02:34 +0000284 m_Holder.SetCaptureData(capturePeriod, counterIds, activeBackends);
James Conroy2dcd3fe2020-02-06 18:34:52 +0000285}
286
Matteo Martincigha84edee2019-10-02 12:50:57 +0100287void ProfilingService::SetCounterValue(uint16_t counterUid, uint32_t value)
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100288{
Matteo Martincighe8485382019-10-10 14:08:21 +0100289 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100290 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100291 ARMNN_ASSERT(counterValuePtr);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100292 counterValuePtr->store(value, std::memory_order::memory_order_relaxed);
293}
294
295uint32_t ProfilingService::AddCounterValue(uint16_t counterUid, uint32_t value)
296{
Matteo Martincighe8485382019-10-10 14:08:21 +0100297 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100298 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100299 ARMNN_ASSERT(counterValuePtr);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100300 return counterValuePtr->fetch_add(value, std::memory_order::memory_order_relaxed);
301}
302
303uint32_t ProfilingService::SubtractCounterValue(uint16_t counterUid, uint32_t value)
304{
Matteo Martincighe8485382019-10-10 14:08:21 +0100305 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100306 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100307 ARMNN_ASSERT(counterValuePtr);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100308 return counterValuePtr->fetch_sub(value, std::memory_order::memory_order_relaxed);
309}
310
311uint32_t ProfilingService::IncrementCounterValue(uint16_t counterUid)
312{
Matteo Martincighe8485382019-10-10 14:08:21 +0100313 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100314 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100315 ARMNN_ASSERT(counterValuePtr);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100316 return counterValuePtr->operator++(std::memory_order::memory_order_relaxed);
317}
318
Jim Flynn00f3aaf2019-10-24 11:58:06 +0100319ProfilingDynamicGuid ProfilingService::NextGuid()
320{
Sadik Armagan3184c902020-03-18 10:57:30 +0000321 return ProfilingService::GetNextGuid();
Jim Flynn00f3aaf2019-10-24 11:58:06 +0100322}
323
324ProfilingStaticGuid ProfilingService::GenerateStaticId(const std::string& str)
325{
Sadik Armagan3184c902020-03-18 10:57:30 +0000326 return ProfilingService::GetStaticId(str);
Jim Flynn00f3aaf2019-10-24 11:58:06 +0100327}
328
Jim Flynn8b200652019-10-24 18:07:44 +0100329std::unique_ptr<ISendTimelinePacket> ProfilingService::GetSendTimelinePacket() const
330{
331 return m_TimelinePacketWriterFactory.GetSendTimelinePacket();
332}
333
Matteo Martincigha84edee2019-10-02 12:50:57 +0100334void ProfilingService::Initialize()
335{
Matteo Martincigha84edee2019-10-02 12:50:57 +0100336 // Register a category for the basic runtime counters
337 if (!m_CounterDirectory.IsCategoryRegistered("ArmNN_Runtime"))
338 {
339 m_CounterDirectory.RegisterCategory("ArmNN_Runtime");
340 }
341
Keith Davise394bd92019-12-02 15:12:19 +0000342 // Register a counter for the number of Network loads
343 if (!m_CounterDirectory.IsCounterRegistered("Network loads"))
Matteo Martincigha84edee2019-10-02 12:50:57 +0100344 {
345 const Counter* loadedNetworksCounter =
Keith Davise394bd92019-12-02 15:12:19 +0000346 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
347 armnn::profiling::NETWORK_LOADS,
348 "ArmNN_Runtime",
Finn Williamsf3fcf322020-05-11 14:38:02 +0100349 0,
Matteo Martincigha84edee2019-10-02 12:50:57 +0100350 0,
351 1.f,
Keith Davise394bd92019-12-02 15:12:19 +0000352 "Network loads",
Matteo Martincigha84edee2019-10-02 12:50:57 +0100353 "The number of networks loaded at runtime",
354 std::string("networks"));
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100355 ARMNN_ASSERT(loadedNetworksCounter);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100356 InitializeCounterValue(loadedNetworksCounter->m_Uid);
357 }
Keith Davise394bd92019-12-02 15:12:19 +0000358 // Register a counter for the number of unloaded networks
359 if (!m_CounterDirectory.IsCounterRegistered("Network unloads"))
Matteo Martincigha84edee2019-10-02 12:50:57 +0100360 {
Keith Davise394bd92019-12-02 15:12:19 +0000361 const Counter* unloadedNetworksCounter =
362 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
363 armnn::profiling::NETWORK_UNLOADS,
364 "ArmNN_Runtime",
Finn Williamsf3fcf322020-05-11 14:38:02 +0100365 0,
Matteo Martincigha84edee2019-10-02 12:50:57 +0100366 0,
367 1.f,
Keith Davise394bd92019-12-02 15:12:19 +0000368 "Network unloads",
369 "The number of networks unloaded at runtime",
370 std::string("networks"));
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100371 ARMNN_ASSERT(unloadedNetworksCounter);
Keith Davise394bd92019-12-02 15:12:19 +0000372 InitializeCounterValue(unloadedNetworksCounter->m_Uid);
373 }
374 // Register a counter for the number of registered backends
375 if (!m_CounterDirectory.IsCounterRegistered("Backends registered"))
376 {
377 const Counter* registeredBackendsCounter =
378 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
379 armnn::profiling::REGISTERED_BACKENDS,
380 "ArmNN_Runtime",
Finn Williamsf3fcf322020-05-11 14:38:02 +0100381 0,
Keith Davise394bd92019-12-02 15:12:19 +0000382 0,
383 1.f,
384 "Backends registered",
Matteo Martincigha84edee2019-10-02 12:50:57 +0100385 "The number of registered backends",
386 std::string("backends"));
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100387 ARMNN_ASSERT(registeredBackendsCounter);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100388 InitializeCounterValue(registeredBackendsCounter->m_Uid);
Finn Williams45a73622020-05-15 18:41:05 +0100389
390 // Due to backends being registered before the profiling service becomes active,
391 // we need to set the counter to the correct value here
392 SetCounterValue(armnn::profiling::REGISTERED_BACKENDS, static_cast<uint32_t>(BackendRegistryInstance().Size()));
Matteo Martincigha84edee2019-10-02 12:50:57 +0100393 }
Keith Davise394bd92019-12-02 15:12:19 +0000394 // Register a counter for the number of registered backends
395 if (!m_CounterDirectory.IsCounterRegistered("Backends unregistered"))
396 {
397 const Counter* unregisteredBackendsCounter =
398 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
399 armnn::profiling::UNREGISTERED_BACKENDS,
400 "ArmNN_Runtime",
Finn Williamsf3fcf322020-05-11 14:38:02 +0100401 0,
Keith Davise394bd92019-12-02 15:12:19 +0000402 0,
403 1.f,
404 "Backends unregistered",
405 "The number of unregistered backends",
406 std::string("backends"));
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100407 ARMNN_ASSERT(unregisteredBackendsCounter);
Keith Davise394bd92019-12-02 15:12:19 +0000408 InitializeCounterValue(unregisteredBackendsCounter->m_Uid);
409 }
Matteo Martincigha84edee2019-10-02 12:50:57 +0100410 // Register a counter for the number of inferences run
411 if (!m_CounterDirectory.IsCounterRegistered("Inferences run"))
412 {
413 const Counter* inferencesRunCounter =
Keith Davise394bd92019-12-02 15:12:19 +0000414 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
415 armnn::profiling::INFERENCES_RUN,
416 "ArmNN_Runtime",
Finn Williamsf3fcf322020-05-11 14:38:02 +0100417 0,
Matteo Martincigha84edee2019-10-02 12:50:57 +0100418 0,
419 1.f,
420 "Inferences run",
421 "The number of inferences run",
422 std::string("inferences"));
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100423 ARMNN_ASSERT(inferencesRunCounter);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100424 InitializeCounterValue(inferencesRunCounter->m_Uid);
425 }
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100426}
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100427
Matteo Martincigha84edee2019-10-02 12:50:57 +0100428void ProfilingService::InitializeCounterValue(uint16_t counterUid)
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100429{
Matteo Martincigha84edee2019-10-02 12:50:57 +0100430 // Increase the size of the counter index if necessary
431 if (counterUid >= m_CounterIndex.size())
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100432 {
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100433 m_CounterIndex.resize(armnn::numeric_cast<size_t>(counterUid) + 1);
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100434 }
Matteo Martincigha84edee2019-10-02 12:50:57 +0100435
436 // Create a new atomic counter and add it to the list
437 m_CounterValues.emplace_back(0);
438
439 // Register the new counter to the counter index for quick access
440 std::atomic<uint32_t>* counterValuePtr = &(m_CounterValues.back());
441 m_CounterIndex.at(counterUid) = counterValuePtr;
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100442}
443
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100444void ProfilingService::Reset()
445{
Matteo Martincigh8d9590e2019-10-15 09:35:29 +0100446 // Stop the profiling service...
Jim Flynn53e46992019-10-14 12:31:10 +0100447 Stop();
Matteo Martincigh8d9590e2019-10-15 09:35:29 +0100448
Jim Flynn53e46992019-10-14 12:31:10 +0100449 // ...then delete all the counter data and configuration...
450 m_CounterIndex.clear();
451 m_CounterValues.clear();
452 m_CounterDirectory.Clear();
Jim Flynn97897022020-02-02 12:52:59 +0000453 m_CounterIdMap.Reset();
Finn Williams09ad6f92019-12-19 17:05:18 +0000454 m_BufferManager.Reset();
Matteo Martincighd0613b52019-10-09 16:47:04 +0100455
Jim Flynn53e46992019-10-14 12:31:10 +0100456 // ...finally reset the profiling state machine
457 m_StateMachine.Reset();
Colm Donelan1aff3932020-02-05 17:48:59 +0000458 m_BackendProfilingContexts.clear();
Keith Davis33ed2212020-03-30 10:43:41 +0100459 m_MaxGlobalCounterId = armnn::profiling::MAX_ARMNN_COUNTER;
Jim Flynn53e46992019-10-14 12:31:10 +0100460}
461
462void ProfilingService::Stop()
463{
Jim Flynn6398a982020-05-27 17:05:21 +0100464 { // only lock when we are updating the inference completed variable
465 std::unique_lock<std::mutex> lck(m_ServiceActiveMutex);
466 m_ServiceActive = false;
467 }
Matteo Martincighd0613b52019-10-09 16:47:04 +0100468 // The order in which we reset/stop the components is not trivial!
Finn Williams09ad6f92019-12-19 17:05:18 +0000469 // First stop the producing threads
470 // Command Handler first as it is responsible for launching then Periodic Counter capture thread
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100471 m_CommandHandler.Stop();
Matteo Martincighe8485382019-10-10 14:08:21 +0100472 m_PeriodicCounterCapture.Stop();
Finn Williams09ad6f92019-12-19 17:05:18 +0000473 // The the consuming thread
Sadik Armagan3896b472020-02-10 12:24:15 +0000474 m_SendThread.Stop(false);
Matteo Martincighd0613b52019-10-09 16:47:04 +0100475
Matteo Martincigh8d9590e2019-10-15 09:35:29 +0100476 // ...then close and destroy the profiling connection...
Jim Flynn53e46992019-10-14 12:31:10 +0100477 if (m_ProfilingConnection != nullptr && m_ProfilingConnection->IsOpen())
478 {
479 m_ProfilingConnection->Close();
480 }
Matteo Martincighd0613b52019-10-09 16:47:04 +0100481 m_ProfilingConnection.reset();
482
Matteo Martincigh8d9590e2019-10-15 09:35:29 +0100483 // ...then move to the "NotConnected" state
Jim Flynn53e46992019-10-14 12:31:10 +0100484 m_StateMachine.TransitionToState(ProfilingState::NotConnected);
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100485}
486
Matteo Martincighe8485382019-10-10 14:08:21 +0100487inline void ProfilingService::CheckCounterUid(uint16_t counterUid) const
488{
489 if (!IsCounterRegistered(counterUid))
490 {
Jan Eilers156113c2020-09-09 19:11:16 +0100491 throw InvalidArgumentException(fmt::format("Counter UID {} is not registered", counterUid));
Matteo Martincighe8485382019-10-10 14:08:21 +0100492 }
493}
494
Keith Davis33ed2212020-03-30 10:43:41 +0100495void ProfilingService::NotifyBackendsForTimelineReporting()
496{
497 BackendProfilingContext::iterator it = m_BackendProfilingContexts.begin();
498 while (it != m_BackendProfilingContexts.end())
499 {
500 auto& backendProfilingContext = it->second;
501 backendProfilingContext->EnableTimelineReporting(m_TimelineReporting);
502 // Increment the Iterator to point to next entry
503 it++;
504 }
505}
506
Jim Flynn6398a982020-05-27 17:05:21 +0100507void ProfilingService::NotifyProfilingServiceActive()
508{
509 { // only lock when we are updating the inference completed variable
510 std::unique_lock<std::mutex> lck(m_ServiceActiveMutex);
511 m_ServiceActive = true;
512 }
513 m_ServiceActiveConditionVariable.notify_one();
514}
515
516void ProfilingService::WaitForProfilingServiceActivation(unsigned int timeout)
517{
518 std::unique_lock<std::mutex> lck(m_ServiceActiveMutex);
519
520 auto start = std::chrono::high_resolution_clock::now();
521 // Here we we will go back to sleep after a spurious wake up if
522 // m_InferenceCompleted is not yet true.
523 if (!m_ServiceActiveConditionVariable.wait_for(lck,
524 std::chrono::milliseconds(timeout),
525 [&]{return m_ServiceActive == true;}))
526 {
527 if (m_ServiceActive == true)
528 {
529 return;
530 }
531 auto finish = std::chrono::high_resolution_clock::now();
532 std::chrono::duration<double, std::milli> elapsed = finish - start;
533 std::stringstream ss;
534 ss << "Timed out waiting on profiling service activation for " << elapsed.count() << " ms";
535 ARMNN_LOG(warning) << ss.str();
536 }
537 return;
538}
539
janeil01811ca552019-12-03 17:01:32 +0000540ProfilingService::~ProfilingService()
541{
542 Stop();
543}
Keith Davis02356de2019-08-26 18:28:17 +0100544} // namespace profiling
545
Matteo Martincigha84edee2019-10-02 12:50:57 +0100546} // namespace armnn