blob: f111de15db7b482b05454ace3098e427b5ded15f [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
Keith Davise394bd92019-12-02 15:12:19 +00008#include <armnn/BackendId.hpp>
Derek Lamberti08446972019-11-26 16:38:31 +00009#include <armnn/Logging.hpp>
Sadik Armagana97a0be2020-03-03 10:44:56 +000010#include <common/include/SocketConnectionException.hpp>
Derek Lamberti08446972019-11-26 16:38:31 +000011
Matteo Martincigha84edee2019-10-02 12:50:57 +010012#include <boost/format.hpp>
13
Keith Davis02356de2019-08-26 18:28:17 +010014namespace armnn
15{
16
17namespace profiling
18{
19
Matteo Martincigha84edee2019-10-02 12:50:57 +010020void ProfilingService::ResetExternalProfilingOptions(const ExternalProfilingOptions& options,
21 bool resetProfilingService)
Keith Davis02356de2019-08-26 18:28:17 +010022{
Matteo Martincigha84edee2019-10-02 12:50:57 +010023 // Update the profiling options
24 m_Options = options;
Keith Davis02356de2019-08-26 18:28:17 +010025
Matteo Martincigh54fb9572019-10-02 12:50:57 +010026 // Check if the profiling service needs to be reset
Matteo Martincigha84edee2019-10-02 12:50:57 +010027 if (resetProfilingService)
Keith Davis02356de2019-08-26 18:28:17 +010028 {
Matteo Martincigha84edee2019-10-02 12:50:57 +010029 // Reset the profiling service
Matteo Martincigh54fb9572019-10-02 12:50:57 +010030 Reset();
Keith Davis02356de2019-08-26 18:28:17 +010031 }
32}
33
Jim Flynn64063552020-02-14 10:18:08 +000034bool ProfilingService::IsProfilingEnabled() const
Keith Davise394bd92019-12-02 15:12:19 +000035{
36 return m_Options.m_EnableProfiling;
37}
38
Jim Flynn672d06e2019-10-15 10:18:11 +010039ProfilingState ProfilingService::ConfigureProfilingService(
40 const ExternalProfilingOptions& options,
41 bool resetProfilingService)
42{
43 ResetExternalProfilingOptions(options, resetProfilingService);
44 ProfilingState currentState = m_StateMachine.GetCurrentState();
45 if (options.m_EnableProfiling)
46 {
47 switch (currentState)
48 {
49 case ProfilingState::Uninitialised:
50 Update(); // should transition to NotConnected
51 Update(); // will either stay in NotConnected because there is no server
52 // or will enter WaitingForAck.
53 currentState = m_StateMachine.GetCurrentState();
54 if (currentState == ProfilingState::WaitingForAck)
55 {
56 Update(); // poke it again to send out the metadata packet
57 }
58 currentState = m_StateMachine.GetCurrentState();
59 return currentState;
60 case ProfilingState::NotConnected:
61 Update(); // will either stay in NotConnected because there is no server
62 // or will enter WaitingForAck
63 currentState = m_StateMachine.GetCurrentState();
64 if (currentState == ProfilingState::WaitingForAck)
65 {
66 Update(); // poke it again to send out the metadata packet
67 }
68 currentState = m_StateMachine.GetCurrentState();
69 return currentState;
70 default:
71 return currentState;
72 }
73 }
74 else
75 {
76 // Make sure profiling is shutdown
77 switch (currentState)
78 {
79 case ProfilingState::Uninitialised:
80 case ProfilingState::NotConnected:
81 return currentState;
82 default:
83 Stop();
84 return m_StateMachine.GetCurrentState();
85 }
86 }
87}
88
Matteo Martincigh54fb9572019-10-02 12:50:57 +010089void ProfilingService::Update()
Keith Davis02356de2019-08-26 18:28:17 +010090{
Matteo Martincigh54fb9572019-10-02 12:50:57 +010091 if (!m_Options.m_EnableProfiling)
Matteo Martincigha84edee2019-10-02 12:50:57 +010092 {
Matteo Martincigh54fb9572019-10-02 12:50:57 +010093 // Don't run if profiling is disabled
94 return;
Matteo Martincigha84edee2019-10-02 12:50:57 +010095 }
Matteo Martincigh54fb9572019-10-02 12:50:57 +010096
97 ProfilingState currentState = m_StateMachine.GetCurrentState();
98 switch (currentState)
Keith Davis02356de2019-08-26 18:28:17 +010099 {
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100100 case ProfilingState::Uninitialised:
janeil01811ca552019-12-03 17:01:32 +0000101
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100102 // Initialize the profiling service
103 Initialize();
104
105 // Move to the next state
106 m_StateMachine.TransitionToState(ProfilingState::NotConnected);
107 break;
108 case ProfilingState::NotConnected:
Matteo Martincighd0613b52019-10-09 16:47:04 +0100109 // Stop the command thread (if running)
110 m_CommandHandler.Stop();
111
112 // Stop the send thread (if running)
Sadik Armagan3896b472020-02-10 12:24:15 +0000113 m_SendThread.Stop(false);
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100114
Matteo Martincighe8485382019-10-10 14:08:21 +0100115 // Stop the periodic counter capture thread (if running)
116 m_PeriodicCounterCapture.Stop();
117
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100118 // Reset any existing profiling connection
119 m_ProfilingConnection.reset();
120
Sadik Armaganbd9e2c52019-09-26 23:13:31 +0100121 try
Keith Davis02356de2019-08-26 18:28:17 +0100122 {
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100123 // Setup the profiling connection
Matteo Martincighd0613b52019-10-09 16:47:04 +0100124 BOOST_ASSERT(m_ProfilingConnectionFactory);
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100125 m_ProfilingConnection = m_ProfilingConnectionFactory->GetProfilingConnection(m_Options);
Keith Davis02356de2019-08-26 18:28:17 +0100126 }
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100127 catch (const Exception& e)
Sadik Armaganbd9e2c52019-09-26 23:13:31 +0100128 {
Derek Lamberti08446972019-11-26 16:38:31 +0000129 ARMNN_LOG(warning) << "An error has occurred when creating the profiling connection: "
130 << e.what();
Sadik Armaganbd9e2c52019-09-26 23:13:31 +0100131 }
Sadik Armagana97a0be2020-03-03 10:44:56 +0000132 catch (const armnnProfiling::SocketConnectionException& e)
133 {
134 ARMNN_LOG(warning) << "An error has occurred when creating the profiling connection ["
135 << e.what() << "] on socket [" << e.GetSocketFd() << "].";
136 }
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100137
138 // Move to the next state
139 m_StateMachine.TransitionToState(m_ProfilingConnection
140 ? ProfilingState::WaitingForAck // Profiling connection obtained, wait for ack
141 : ProfilingState::NotConnected); // Profiling connection failed, stay in the
142 // "NotConnected" state
143 break;
144 case ProfilingState::WaitingForAck:
145 BOOST_ASSERT(m_ProfilingConnection);
146
147 // Start the command thread
148 m_CommandHandler.Start(*m_ProfilingConnection);
149
150 // Start the send thread, while in "WaitingForAck" state it'll send out a "Stream MetaData" packet waiting for
151 // a valid "Connection Acknowledged" packet confirming the connection
Sadik Armagan3896b472020-02-10 12:24:15 +0000152 m_SendThread.Start(*m_ProfilingConnection);
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100153
154 // The connection acknowledged command handler will automatically transition the state to "Active" once a
155 // valid "Connection Acknowledged" packet has been received
156
157 break;
158 case ProfilingState::Active:
159
Matteo Martincighe8485382019-10-10 14:08:21 +0100160 // The period counter capture thread is started by the Periodic Counter Selection command handler upon
161 // request by an external profiling service
162
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100163 break;
164 default:
165 throw RuntimeException(boost::str(boost::format("Unknown profiling service state: %1")
166 % static_cast<int>(currentState)));
Sadik Armaganbd9e2c52019-09-26 23:13:31 +0100167 }
Keith Davis02356de2019-08-26 18:28:17 +0100168}
169
Jim Flynn53e46992019-10-14 12:31:10 +0100170void ProfilingService::Disconnect()
171{
172 ProfilingState currentState = m_StateMachine.GetCurrentState();
173 switch (currentState)
174 {
175 case ProfilingState::Uninitialised:
176 case ProfilingState::NotConnected:
177 case ProfilingState::WaitingForAck:
178 return; // NOP
179 case ProfilingState::Active:
180 // Stop the command thread (if running)
181 Stop();
182
183 break;
184 default:
185 throw RuntimeException(boost::str(boost::format("Unknown profiling service state: %1")
186 % static_cast<int>(currentState)));
187 }
188}
189
David Monahanc1536d62020-02-12 15:52:35 +0000190// Store a profiling context returned from a backend that support profiling, and register its counters
191void ProfilingService::AddBackendProfilingContext(const BackendId backendId,
192 std::shared_ptr<armnn::profiling::IBackendProfilingContext> profilingContext)
193{
194 BOOST_ASSERT(profilingContext != nullptr);
195 // Register the backend counters
196 m_MaxGlobalCounterId = profilingContext->RegisterCounters(m_MaxGlobalCounterId);
197 m_BackendProfilingContexts.emplace(backendId, std::move(profilingContext));
198}
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100199const ICounterDirectory& ProfilingService::GetCounterDirectory() const
200{
201 return m_CounterDirectory;
202}
203
Jim Flynn97897022020-02-02 12:52:59 +0000204ICounterRegistry& ProfilingService::GetCounterRegistry()
205{
206 return m_CounterDirectory;
207}
208
Matteo Martincigha84edee2019-10-02 12:50:57 +0100209ProfilingState ProfilingService::GetCurrentState() const
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100210{
Matteo Martincigha84edee2019-10-02 12:50:57 +0100211 return m_StateMachine.GetCurrentState();
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100212}
213
214uint16_t ProfilingService::GetCounterCount() const
215{
216 return m_CounterDirectory.GetCounterCount();
217}
218
Matteo Martincighe8485382019-10-10 14:08:21 +0100219bool ProfilingService::IsCounterRegistered(uint16_t counterUid) const
220{
221 return counterUid < m_CounterIndex.size();
222}
223
Matteo Martincigha84edee2019-10-02 12:50:57 +0100224uint32_t ProfilingService::GetCounterValue(uint16_t counterUid) const
Keith Davis02356de2019-08-26 18:28:17 +0100225{
Matteo Martincighe8485382019-10-10 14:08:21 +0100226 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100227 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
228 BOOST_ASSERT(counterValuePtr);
229 return counterValuePtr->load(std::memory_order::memory_order_relaxed);
Keith Davis02356de2019-08-26 18:28:17 +0100230}
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100231
Jim Flynn8e0c7a62020-01-30 14:10:55 +0000232const ICounterMappings& ProfilingService::GetCounterMappings() const
233{
234 return m_CounterIdMap;
235}
236
Jim Flynn97897022020-02-02 12:52:59 +0000237IRegisterCounterMapping& ProfilingService::GetCounterMappingRegistry()
Jim Flynn8e0c7a62020-01-30 14:10:55 +0000238{
239 return m_CounterIdMap;
240}
241
James Conroy2dcd3fe2020-02-06 18:34:52 +0000242CaptureData ProfilingService::GetCaptureData()
243{
244 return m_Holder.GetCaptureData();
245}
246
Finn Williams032bc742020-02-12 11:02:34 +0000247void ProfilingService::SetCaptureData(uint32_t capturePeriod,
248 const std::vector<uint16_t>& counterIds,
249 const std::set<BackendId>& activeBackends)
James Conroy2dcd3fe2020-02-06 18:34:52 +0000250{
Finn Williams032bc742020-02-12 11:02:34 +0000251 m_Holder.SetCaptureData(capturePeriod, counterIds, activeBackends);
James Conroy2dcd3fe2020-02-06 18:34:52 +0000252}
253
Matteo Martincigha84edee2019-10-02 12:50:57 +0100254void ProfilingService::SetCounterValue(uint16_t counterUid, uint32_t value)
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100255{
Matteo Martincighe8485382019-10-10 14:08:21 +0100256 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100257 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
258 BOOST_ASSERT(counterValuePtr);
259 counterValuePtr->store(value, std::memory_order::memory_order_relaxed);
260}
261
262uint32_t ProfilingService::AddCounterValue(uint16_t counterUid, uint32_t value)
263{
Matteo Martincighe8485382019-10-10 14:08:21 +0100264 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100265 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
266 BOOST_ASSERT(counterValuePtr);
267 return counterValuePtr->fetch_add(value, std::memory_order::memory_order_relaxed);
268}
269
270uint32_t ProfilingService::SubtractCounterValue(uint16_t counterUid, uint32_t value)
271{
Matteo Martincighe8485382019-10-10 14:08:21 +0100272 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100273 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
274 BOOST_ASSERT(counterValuePtr);
275 return counterValuePtr->fetch_sub(value, std::memory_order::memory_order_relaxed);
276}
277
278uint32_t ProfilingService::IncrementCounterValue(uint16_t counterUid)
279{
Matteo Martincighe8485382019-10-10 14:08:21 +0100280 CheckCounterUid(counterUid);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100281 std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
282 BOOST_ASSERT(counterValuePtr);
283 return counterValuePtr->operator++(std::memory_order::memory_order_relaxed);
284}
285
Jim Flynn00f3aaf2019-10-24 11:58:06 +0100286ProfilingDynamicGuid ProfilingService::NextGuid()
287{
288 return m_GuidGenerator.NextGuid();
289}
290
291ProfilingStaticGuid ProfilingService::GenerateStaticId(const std::string& str)
292{
293 return m_GuidGenerator.GenerateStaticId(str);
294}
295
Jim Flynn8b200652019-10-24 18:07:44 +0100296std::unique_ptr<ISendTimelinePacket> ProfilingService::GetSendTimelinePacket() const
297{
298 return m_TimelinePacketWriterFactory.GetSendTimelinePacket();
299}
300
Matteo Martincigha84edee2019-10-02 12:50:57 +0100301void ProfilingService::Initialize()
302{
Matteo Martincigha84edee2019-10-02 12:50:57 +0100303 // Register a category for the basic runtime counters
304 if (!m_CounterDirectory.IsCategoryRegistered("ArmNN_Runtime"))
305 {
306 m_CounterDirectory.RegisterCategory("ArmNN_Runtime");
307 }
308
Keith Davise394bd92019-12-02 15:12:19 +0000309 // Register a counter for the number of Network loads
310 if (!m_CounterDirectory.IsCounterRegistered("Network loads"))
Matteo Martincigha84edee2019-10-02 12:50:57 +0100311 {
312 const Counter* loadedNetworksCounter =
Keith Davise394bd92019-12-02 15:12:19 +0000313 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
314 armnn::profiling::NETWORK_LOADS,
315 "ArmNN_Runtime",
Matteo Martincigha84edee2019-10-02 12:50:57 +0100316 0,
317 0,
318 1.f,
Keith Davise394bd92019-12-02 15:12:19 +0000319 "Network loads",
Matteo Martincigha84edee2019-10-02 12:50:57 +0100320 "The number of networks loaded at runtime",
321 std::string("networks"));
322 BOOST_ASSERT(loadedNetworksCounter);
323 InitializeCounterValue(loadedNetworksCounter->m_Uid);
324 }
Keith Davise394bd92019-12-02 15:12:19 +0000325 // Register a counter for the number of unloaded networks
326 if (!m_CounterDirectory.IsCounterRegistered("Network unloads"))
Matteo Martincigha84edee2019-10-02 12:50:57 +0100327 {
Keith Davise394bd92019-12-02 15:12:19 +0000328 const Counter* unloadedNetworksCounter =
329 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
330 armnn::profiling::NETWORK_UNLOADS,
331 "ArmNN_Runtime",
Matteo Martincigha84edee2019-10-02 12:50:57 +0100332 0,
333 0,
334 1.f,
Keith Davise394bd92019-12-02 15:12:19 +0000335 "Network unloads",
336 "The number of networks unloaded at runtime",
337 std::string("networks"));
338 BOOST_ASSERT(unloadedNetworksCounter);
339 InitializeCounterValue(unloadedNetworksCounter->m_Uid);
340 }
341 // Register a counter for the number of registered backends
342 if (!m_CounterDirectory.IsCounterRegistered("Backends registered"))
343 {
344 const Counter* registeredBackendsCounter =
345 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
346 armnn::profiling::REGISTERED_BACKENDS,
347 "ArmNN_Runtime",
348 0,
349 0,
350 1.f,
351 "Backends registered",
Matteo Martincigha84edee2019-10-02 12:50:57 +0100352 "The number of registered backends",
353 std::string("backends"));
354 BOOST_ASSERT(registeredBackendsCounter);
355 InitializeCounterValue(registeredBackendsCounter->m_Uid);
356 }
Keith Davise394bd92019-12-02 15:12:19 +0000357 // Register a counter for the number of registered backends
358 if (!m_CounterDirectory.IsCounterRegistered("Backends unregistered"))
359 {
360 const Counter* unregisteredBackendsCounter =
361 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
362 armnn::profiling::UNREGISTERED_BACKENDS,
363 "ArmNN_Runtime",
364 0,
365 0,
366 1.f,
367 "Backends unregistered",
368 "The number of unregistered backends",
369 std::string("backends"));
370 BOOST_ASSERT(unregisteredBackendsCounter);
371 InitializeCounterValue(unregisteredBackendsCounter->m_Uid);
372 }
Matteo Martincigha84edee2019-10-02 12:50:57 +0100373 // Register a counter for the number of inferences run
374 if (!m_CounterDirectory.IsCounterRegistered("Inferences run"))
375 {
376 const Counter* inferencesRunCounter =
Keith Davise394bd92019-12-02 15:12:19 +0000377 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
378 armnn::profiling::INFERENCES_RUN,
379 "ArmNN_Runtime",
Matteo Martincigha84edee2019-10-02 12:50:57 +0100380 0,
381 0,
382 1.f,
383 "Inferences run",
384 "The number of inferences run",
385 std::string("inferences"));
386 BOOST_ASSERT(inferencesRunCounter);
387 InitializeCounterValue(inferencesRunCounter->m_Uid);
388 }
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100389}
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100390
Matteo Martincigha84edee2019-10-02 12:50:57 +0100391void ProfilingService::InitializeCounterValue(uint16_t counterUid)
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100392{
Matteo Martincigha84edee2019-10-02 12:50:57 +0100393 // Increase the size of the counter index if necessary
394 if (counterUid >= m_CounterIndex.size())
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100395 {
Matteo Martincigha84edee2019-10-02 12:50:57 +0100396 m_CounterIndex.resize(boost::numeric_cast<size_t>(counterUid) + 1);
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100397 }
Matteo Martincigha84edee2019-10-02 12:50:57 +0100398
399 // Create a new atomic counter and add it to the list
400 m_CounterValues.emplace_back(0);
401
402 // Register the new counter to the counter index for quick access
403 std::atomic<uint32_t>* counterValuePtr = &(m_CounterValues.back());
404 m_CounterIndex.at(counterUid) = counterValuePtr;
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100405}
406
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100407void ProfilingService::Reset()
408{
Matteo Martincigh8d9590e2019-10-15 09:35:29 +0100409 // Stop the profiling service...
Jim Flynn53e46992019-10-14 12:31:10 +0100410 Stop();
Matteo Martincigh8d9590e2019-10-15 09:35:29 +0100411
Jim Flynn53e46992019-10-14 12:31:10 +0100412 // ...then delete all the counter data and configuration...
413 m_CounterIndex.clear();
414 m_CounterValues.clear();
415 m_CounterDirectory.Clear();
Jim Flynn97897022020-02-02 12:52:59 +0000416 m_CounterIdMap.Reset();
Finn Williams09ad6f92019-12-19 17:05:18 +0000417 m_BufferManager.Reset();
Matteo Martincighd0613b52019-10-09 16:47:04 +0100418
Jim Flynn53e46992019-10-14 12:31:10 +0100419 // ...finally reset the profiling state machine
420 m_StateMachine.Reset();
Colm Donelan1aff3932020-02-05 17:48:59 +0000421 m_BackendProfilingContexts.clear();
David Monahanc1536d62020-02-12 15:52:35 +0000422 m_MaxGlobalCounterId = armnn::profiling::INFERENCES_RUN;
Jim Flynn53e46992019-10-14 12:31:10 +0100423}
424
425void ProfilingService::Stop()
426{
Matteo Martincighd0613b52019-10-09 16:47:04 +0100427 // The order in which we reset/stop the components is not trivial!
Finn Williams09ad6f92019-12-19 17:05:18 +0000428 // First stop the producing threads
429 // Command Handler first as it is responsible for launching then Periodic Counter capture thread
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100430 m_CommandHandler.Stop();
Matteo Martincighe8485382019-10-10 14:08:21 +0100431 m_PeriodicCounterCapture.Stop();
Finn Williams09ad6f92019-12-19 17:05:18 +0000432 // The the consuming thread
Sadik Armagan3896b472020-02-10 12:24:15 +0000433 m_SendThread.Stop(false);
Matteo Martincighd0613b52019-10-09 16:47:04 +0100434
Matteo Martincigh8d9590e2019-10-15 09:35:29 +0100435 // ...then close and destroy the profiling connection...
Jim Flynn53e46992019-10-14 12:31:10 +0100436 if (m_ProfilingConnection != nullptr && m_ProfilingConnection->IsOpen())
437 {
438 m_ProfilingConnection->Close();
439 }
Matteo Martincighd0613b52019-10-09 16:47:04 +0100440 m_ProfilingConnection.reset();
441
Matteo Martincigh8d9590e2019-10-15 09:35:29 +0100442 // ...then move to the "NotConnected" state
Jim Flynn53e46992019-10-14 12:31:10 +0100443 m_StateMachine.TransitionToState(ProfilingState::NotConnected);
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100444}
445
Matteo Martincighe8485382019-10-10 14:08:21 +0100446inline void ProfilingService::CheckCounterUid(uint16_t counterUid) const
447{
448 if (!IsCounterRegistered(counterUid))
449 {
450 throw InvalidArgumentException(boost::str(boost::format("Counter UID %1% is not registered") % counterUid));
451 }
452}
453
janeil01811ca552019-12-03 17:01:32 +0000454ProfilingService::~ProfilingService()
455{
456 Stop();
457}
458
Keith Davis02356de2019-08-26 18:28:17 +0100459} // namespace profiling
460
Matteo Martincigha84edee2019-10-02 12:50:57 +0100461} // namespace armnn