1*89c4ff92SAndroid Build Coastguard Worker //
2*89c4ff92SAndroid Build Coastguard Worker // Copyright © 2019, 2022-2023 Arm Ltd and Contributors. All rights reserved.
3*89c4ff92SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
4*89c4ff92SAndroid Build Coastguard Worker //
5*89c4ff92SAndroid Build Coastguard Worker
6*89c4ff92SAndroid Build Coastguard Worker #include "ProfilingService.hpp"
7*89c4ff92SAndroid Build Coastguard Worker
8*89c4ff92SAndroid Build Coastguard Worker #include <common/include/Logging.hpp>
9*89c4ff92SAndroid Build Coastguard Worker #include <common/include/NumericCast.hpp>
10*89c4ff92SAndroid Build Coastguard Worker #include <common/include/ProfilingGuid.hpp>
11*89c4ff92SAndroid Build Coastguard Worker #include <common/include/SocketConnectionException.hpp>
12*89c4ff92SAndroid Build Coastguard Worker
13*89c4ff92SAndroid Build Coastguard Worker #if defined(ARMNN_BUILD_BARE_METAL) || defined(ARMNN_EXECUTE_NETWORK_STATIC)
14*89c4ff92SAndroid Build Coastguard Worker #include <common/include/IgnoreUnused.hpp>
15*89c4ff92SAndroid Build Coastguard Worker #endif
16*89c4ff92SAndroid Build Coastguard Worker
17*89c4ff92SAndroid Build Coastguard Worker
18*89c4ff92SAndroid Build Coastguard Worker #include <fmt/format.h>
19*89c4ff92SAndroid Build Coastguard Worker
20*89c4ff92SAndroid Build Coastguard Worker namespace arm
21*89c4ff92SAndroid Build Coastguard Worker {
22*89c4ff92SAndroid Build Coastguard Worker
23*89c4ff92SAndroid Build Coastguard Worker namespace pipe
24*89c4ff92SAndroid Build Coastguard Worker {
25*89c4ff92SAndroid Build Coastguard Worker
ResetExternalProfilingOptions(const arm::pipe::ProfilingOptions & options,bool resetProfilingService)26*89c4ff92SAndroid Build Coastguard Worker void ProfilingService::ResetExternalProfilingOptions(const arm::pipe::ProfilingOptions& options,
27*89c4ff92SAndroid Build Coastguard Worker bool resetProfilingService)
28*89c4ff92SAndroid Build Coastguard Worker {
29*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
30*89c4ff92SAndroid Build Coastguard Worker // Update the profiling options
31*89c4ff92SAndroid Build Coastguard Worker m_Options = options;
32*89c4ff92SAndroid Build Coastguard Worker m_TimelineReporting = options.m_TimelineEnabled;
33*89c4ff92SAndroid Build Coastguard Worker m_ConnectionAcknowledgedCommandHandler.setTimelineEnabled(options.m_TimelineEnabled);
34*89c4ff92SAndroid Build Coastguard Worker
35*89c4ff92SAndroid Build Coastguard Worker // Check if the profiling service needs to be reset
36*89c4ff92SAndroid Build Coastguard Worker if (resetProfilingService)
37*89c4ff92SAndroid Build Coastguard Worker {
38*89c4ff92SAndroid Build Coastguard Worker // Reset the profiling service
39*89c4ff92SAndroid Build Coastguard Worker Reset();
40*89c4ff92SAndroid Build Coastguard Worker }
41*89c4ff92SAndroid Build Coastguard Worker #else
42*89c4ff92SAndroid Build Coastguard Worker IgnoreUnused(options);
43*89c4ff92SAndroid Build Coastguard Worker IgnoreUnused(resetProfilingService);
44*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL || ARMNN_EXECUTE_NETWORK_STATIC
45*89c4ff92SAndroid Build Coastguard Worker }
46*89c4ff92SAndroid Build Coastguard Worker
IsProfilingEnabled() const47*89c4ff92SAndroid Build Coastguard Worker bool ProfilingService::IsProfilingEnabled() const
48*89c4ff92SAndroid Build Coastguard Worker {
49*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
50*89c4ff92SAndroid Build Coastguard Worker return m_Options.m_EnableProfiling;
51*89c4ff92SAndroid Build Coastguard Worker #else
52*89c4ff92SAndroid Build Coastguard Worker return false;
53*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
54*89c4ff92SAndroid Build Coastguard Worker }
55*89c4ff92SAndroid Build Coastguard Worker
ConfigureProfilingService(const ProfilingOptions & options,bool resetProfilingService)56*89c4ff92SAndroid Build Coastguard Worker ProfilingState ProfilingService::ConfigureProfilingService(
57*89c4ff92SAndroid Build Coastguard Worker const ProfilingOptions& options,
58*89c4ff92SAndroid Build Coastguard Worker bool resetProfilingService)
59*89c4ff92SAndroid Build Coastguard Worker {
60*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
61*89c4ff92SAndroid Build Coastguard Worker ResetExternalProfilingOptions(options, resetProfilingService);
62*89c4ff92SAndroid Build Coastguard Worker ProfilingState currentState = m_StateMachine.GetCurrentState();
63*89c4ff92SAndroid Build Coastguard Worker if (options.m_EnableProfiling)
64*89c4ff92SAndroid Build Coastguard Worker {
65*89c4ff92SAndroid Build Coastguard Worker switch (currentState)
66*89c4ff92SAndroid Build Coastguard Worker {
67*89c4ff92SAndroid Build Coastguard Worker case ProfilingState::Uninitialised:
68*89c4ff92SAndroid Build Coastguard Worker Update(); // should transition to NotConnected
69*89c4ff92SAndroid Build Coastguard Worker Update(); // will either stay in NotConnected because there is no server
70*89c4ff92SAndroid Build Coastguard Worker // or will enter WaitingForAck.
71*89c4ff92SAndroid Build Coastguard Worker currentState = m_StateMachine.GetCurrentState();
72*89c4ff92SAndroid Build Coastguard Worker if (currentState == ProfilingState::WaitingForAck)
73*89c4ff92SAndroid Build Coastguard Worker {
74*89c4ff92SAndroid Build Coastguard Worker Update(); // poke it again to send out the metadata packet
75*89c4ff92SAndroid Build Coastguard Worker }
76*89c4ff92SAndroid Build Coastguard Worker currentState = m_StateMachine.GetCurrentState();
77*89c4ff92SAndroid Build Coastguard Worker return currentState;
78*89c4ff92SAndroid Build Coastguard Worker case ProfilingState::NotConnected:
79*89c4ff92SAndroid Build Coastguard Worker Update(); // will either stay in NotConnected because there is no server
80*89c4ff92SAndroid Build Coastguard Worker // or will enter WaitingForAck
81*89c4ff92SAndroid Build Coastguard Worker currentState = m_StateMachine.GetCurrentState();
82*89c4ff92SAndroid Build Coastguard Worker if (currentState == ProfilingState::WaitingForAck)
83*89c4ff92SAndroid Build Coastguard Worker {
84*89c4ff92SAndroid Build Coastguard Worker Update(); // poke it again to send out the metadata packet
85*89c4ff92SAndroid Build Coastguard Worker }
86*89c4ff92SAndroid Build Coastguard Worker currentState = m_StateMachine.GetCurrentState();
87*89c4ff92SAndroid Build Coastguard Worker return currentState;
88*89c4ff92SAndroid Build Coastguard Worker default:
89*89c4ff92SAndroid Build Coastguard Worker return currentState;
90*89c4ff92SAndroid Build Coastguard Worker }
91*89c4ff92SAndroid Build Coastguard Worker }
92*89c4ff92SAndroid Build Coastguard Worker else
93*89c4ff92SAndroid Build Coastguard Worker {
94*89c4ff92SAndroid Build Coastguard Worker // Make sure profiling is shutdown
95*89c4ff92SAndroid Build Coastguard Worker switch (currentState)
96*89c4ff92SAndroid Build Coastguard Worker {
97*89c4ff92SAndroid Build Coastguard Worker case ProfilingState::Uninitialised:
98*89c4ff92SAndroid Build Coastguard Worker case ProfilingState::NotConnected:
99*89c4ff92SAndroid Build Coastguard Worker return currentState;
100*89c4ff92SAndroid Build Coastguard Worker default:
101*89c4ff92SAndroid Build Coastguard Worker Stop();
102*89c4ff92SAndroid Build Coastguard Worker return m_StateMachine.GetCurrentState();
103*89c4ff92SAndroid Build Coastguard Worker }
104*89c4ff92SAndroid Build Coastguard Worker }
105*89c4ff92SAndroid Build Coastguard Worker #else
106*89c4ff92SAndroid Build Coastguard Worker IgnoreUnused(options);
107*89c4ff92SAndroid Build Coastguard Worker IgnoreUnused(resetProfilingService);
108*89c4ff92SAndroid Build Coastguard Worker return ProfilingState::Uninitialised;
109*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
110*89c4ff92SAndroid Build Coastguard Worker }
111*89c4ff92SAndroid Build Coastguard Worker
Update()112*89c4ff92SAndroid Build Coastguard Worker void ProfilingService::Update()
113*89c4ff92SAndroid Build Coastguard Worker {
114*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
115*89c4ff92SAndroid Build Coastguard Worker if (!m_Options.m_EnableProfiling)
116*89c4ff92SAndroid Build Coastguard Worker {
117*89c4ff92SAndroid Build Coastguard Worker // Don't run if profiling is disabled
118*89c4ff92SAndroid Build Coastguard Worker return;
119*89c4ff92SAndroid Build Coastguard Worker }
120*89c4ff92SAndroid Build Coastguard Worker
121*89c4ff92SAndroid Build Coastguard Worker ProfilingState currentState = m_StateMachine.GetCurrentState();
122*89c4ff92SAndroid Build Coastguard Worker switch (currentState)
123*89c4ff92SAndroid Build Coastguard Worker {
124*89c4ff92SAndroid Build Coastguard Worker case ProfilingState::Uninitialised:
125*89c4ff92SAndroid Build Coastguard Worker
126*89c4ff92SAndroid Build Coastguard Worker // Initialize the profiling service
127*89c4ff92SAndroid Build Coastguard Worker Initialize();
128*89c4ff92SAndroid Build Coastguard Worker
129*89c4ff92SAndroid Build Coastguard Worker // Move to the next state
130*89c4ff92SAndroid Build Coastguard Worker m_StateMachine.TransitionToState(ProfilingState::NotConnected);
131*89c4ff92SAndroid Build Coastguard Worker break;
132*89c4ff92SAndroid Build Coastguard Worker case ProfilingState::NotConnected:
133*89c4ff92SAndroid Build Coastguard Worker // Stop the command thread (if running)
134*89c4ff92SAndroid Build Coastguard Worker m_CommandHandler.Stop();
135*89c4ff92SAndroid Build Coastguard Worker
136*89c4ff92SAndroid Build Coastguard Worker // Stop the send thread (if running)
137*89c4ff92SAndroid Build Coastguard Worker m_SendThread.Stop(false);
138*89c4ff92SAndroid Build Coastguard Worker
139*89c4ff92SAndroid Build Coastguard Worker // Stop the periodic counter capture thread (if running)
140*89c4ff92SAndroid Build Coastguard Worker m_PeriodicCounterCapture.Stop();
141*89c4ff92SAndroid Build Coastguard Worker
142*89c4ff92SAndroid Build Coastguard Worker // Reset any existing profiling connection
143*89c4ff92SAndroid Build Coastguard Worker m_ProfilingConnection.reset();
144*89c4ff92SAndroid Build Coastguard Worker
145*89c4ff92SAndroid Build Coastguard Worker try
146*89c4ff92SAndroid Build Coastguard Worker {
147*89c4ff92SAndroid Build Coastguard Worker // Setup the profiling connection
148*89c4ff92SAndroid Build Coastguard Worker ARM_PIPE_ASSERT(m_ProfilingConnectionFactory);
149*89c4ff92SAndroid Build Coastguard Worker m_ProfilingConnection = m_ProfilingConnectionFactory->GetProfilingConnection(m_Options);
150*89c4ff92SAndroid Build Coastguard Worker }
151*89c4ff92SAndroid Build Coastguard Worker catch (const arm::pipe::ProfilingException& e)
152*89c4ff92SAndroid Build Coastguard Worker {
153*89c4ff92SAndroid Build Coastguard Worker ARM_PIPE_LOG(warning) << "An error has occurred when creating the profiling connection: "
154*89c4ff92SAndroid Build Coastguard Worker << e.what();
155*89c4ff92SAndroid Build Coastguard Worker }
156*89c4ff92SAndroid Build Coastguard Worker catch (const arm::pipe::SocketConnectionException& e)
157*89c4ff92SAndroid Build Coastguard Worker {
158*89c4ff92SAndroid Build Coastguard Worker ARM_PIPE_LOG(warning) << "An error has occurred when creating the profiling connection ["
159*89c4ff92SAndroid Build Coastguard Worker << e.what() << "] on socket [" << e.GetSocketFd() << "].";
160*89c4ff92SAndroid Build Coastguard Worker }
161*89c4ff92SAndroid Build Coastguard Worker
162*89c4ff92SAndroid Build Coastguard Worker // Move to the next state
163*89c4ff92SAndroid Build Coastguard Worker m_StateMachine.TransitionToState(m_ProfilingConnection
164*89c4ff92SAndroid Build Coastguard Worker ? ProfilingState::WaitingForAck // Profiling connection obtained, wait for ack
165*89c4ff92SAndroid Build Coastguard Worker : ProfilingState::NotConnected); // Profiling connection failed, stay in the
166*89c4ff92SAndroid Build Coastguard Worker // "NotConnected" state
167*89c4ff92SAndroid Build Coastguard Worker break;
168*89c4ff92SAndroid Build Coastguard Worker case ProfilingState::WaitingForAck:
169*89c4ff92SAndroid Build Coastguard Worker ARM_PIPE_ASSERT(m_ProfilingConnection);
170*89c4ff92SAndroid Build Coastguard Worker
171*89c4ff92SAndroid Build Coastguard Worker // Start the command thread
172*89c4ff92SAndroid Build Coastguard Worker m_CommandHandler.Start(*m_ProfilingConnection);
173*89c4ff92SAndroid Build Coastguard Worker
174*89c4ff92SAndroid Build Coastguard Worker // Start the send thread, while in "WaitingForAck" state it'll send out a "Stream MetaData" packet waiting for
175*89c4ff92SAndroid Build Coastguard Worker // a valid "Connection Acknowledged" packet confirming the connection
176*89c4ff92SAndroid Build Coastguard Worker m_SendThread.Start(*m_ProfilingConnection);
177*89c4ff92SAndroid Build Coastguard Worker
178*89c4ff92SAndroid Build Coastguard Worker // The connection acknowledged command handler will automatically transition the state to "Active" once a
179*89c4ff92SAndroid Build Coastguard Worker // valid "Connection Acknowledged" packet has been received
180*89c4ff92SAndroid Build Coastguard Worker
181*89c4ff92SAndroid Build Coastguard Worker break;
182*89c4ff92SAndroid Build Coastguard Worker case ProfilingState::Active:
183*89c4ff92SAndroid Build Coastguard Worker
184*89c4ff92SAndroid Build Coastguard Worker // The period counter capture thread is started by the Periodic Counter Selection command handler upon
185*89c4ff92SAndroid Build Coastguard Worker // request by an external profiling service
186*89c4ff92SAndroid Build Coastguard Worker
187*89c4ff92SAndroid Build Coastguard Worker break;
188*89c4ff92SAndroid Build Coastguard Worker default:
189*89c4ff92SAndroid Build Coastguard Worker throw arm::pipe::ProfilingException(fmt::format("Unknown profiling service state: {}",
190*89c4ff92SAndroid Build Coastguard Worker static_cast<int>(currentState)));
191*89c4ff92SAndroid Build Coastguard Worker }
192*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
193*89c4ff92SAndroid Build Coastguard Worker }
194*89c4ff92SAndroid Build Coastguard Worker
Disconnect()195*89c4ff92SAndroid Build Coastguard Worker void ProfilingService::Disconnect()
196*89c4ff92SAndroid Build Coastguard Worker {
197*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
198*89c4ff92SAndroid Build Coastguard Worker ProfilingState currentState = m_StateMachine.GetCurrentState();
199*89c4ff92SAndroid Build Coastguard Worker switch (currentState)
200*89c4ff92SAndroid Build Coastguard Worker {
201*89c4ff92SAndroid Build Coastguard Worker case ProfilingState::Uninitialised:
202*89c4ff92SAndroid Build Coastguard Worker case ProfilingState::NotConnected:
203*89c4ff92SAndroid Build Coastguard Worker case ProfilingState::WaitingForAck:
204*89c4ff92SAndroid Build Coastguard Worker return; // NOP
205*89c4ff92SAndroid Build Coastguard Worker case ProfilingState::Active:
206*89c4ff92SAndroid Build Coastguard Worker // Stop the command thread (if running)
207*89c4ff92SAndroid Build Coastguard Worker Stop();
208*89c4ff92SAndroid Build Coastguard Worker
209*89c4ff92SAndroid Build Coastguard Worker break;
210*89c4ff92SAndroid Build Coastguard Worker default:
211*89c4ff92SAndroid Build Coastguard Worker throw arm::pipe::ProfilingException(fmt::format("Unknown profiling service state: {}",
212*89c4ff92SAndroid Build Coastguard Worker static_cast<int>(currentState)));
213*89c4ff92SAndroid Build Coastguard Worker }
214*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
215*89c4ff92SAndroid Build Coastguard Worker }
216*89c4ff92SAndroid Build Coastguard Worker
217*89c4ff92SAndroid Build Coastguard Worker // Store a profiling context returned from a backend that support profiling, and register its counters
AddBackendProfilingContext(const std::string & backendId,std::shared_ptr<IBackendProfilingContext> profilingContext)218*89c4ff92SAndroid Build Coastguard Worker void ProfilingService::AddBackendProfilingContext(
219*89c4ff92SAndroid Build Coastguard Worker const std::string& backendId,
220*89c4ff92SAndroid Build Coastguard Worker std::shared_ptr<IBackendProfilingContext> profilingContext)
221*89c4ff92SAndroid Build Coastguard Worker {
222*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
223*89c4ff92SAndroid Build Coastguard Worker ARM_PIPE_ASSERT(profilingContext != nullptr);
224*89c4ff92SAndroid Build Coastguard Worker // Register the backend counters
225*89c4ff92SAndroid Build Coastguard Worker m_MaxGlobalCounterId = profilingContext->RegisterCounters(m_MaxGlobalCounterId);
226*89c4ff92SAndroid Build Coastguard Worker m_BackendProfilingContexts.emplace(backendId, std::move(profilingContext));
227*89c4ff92SAndroid Build Coastguard Worker #else
228*89c4ff92SAndroid Build Coastguard Worker IgnoreUnused(backendId);
229*89c4ff92SAndroid Build Coastguard Worker IgnoreUnused(profilingContext);
230*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
231*89c4ff92SAndroid Build Coastguard Worker }
GetCounterDirectory() const232*89c4ff92SAndroid Build Coastguard Worker const ICounterDirectory& ProfilingService::GetCounterDirectory() const
233*89c4ff92SAndroid Build Coastguard Worker {
234*89c4ff92SAndroid Build Coastguard Worker return m_CounterDirectory;
235*89c4ff92SAndroid Build Coastguard Worker }
236*89c4ff92SAndroid Build Coastguard Worker
GetCounterRegistry()237*89c4ff92SAndroid Build Coastguard Worker ICounterRegistry& ProfilingService::GetCounterRegistry()
238*89c4ff92SAndroid Build Coastguard Worker {
239*89c4ff92SAndroid Build Coastguard Worker return m_CounterDirectory;
240*89c4ff92SAndroid Build Coastguard Worker }
241*89c4ff92SAndroid Build Coastguard Worker
GetCurrentState() const242*89c4ff92SAndroid Build Coastguard Worker ProfilingState ProfilingService::GetCurrentState() const
243*89c4ff92SAndroid Build Coastguard Worker {
244*89c4ff92SAndroid Build Coastguard Worker return m_StateMachine.GetCurrentState();
245*89c4ff92SAndroid Build Coastguard Worker }
246*89c4ff92SAndroid Build Coastguard Worker
GetCounterCount() const247*89c4ff92SAndroid Build Coastguard Worker uint16_t ProfilingService::GetCounterCount() const
248*89c4ff92SAndroid Build Coastguard Worker {
249*89c4ff92SAndroid Build Coastguard Worker return m_CounterDirectory.GetCounterCount();
250*89c4ff92SAndroid Build Coastguard Worker }
251*89c4ff92SAndroid Build Coastguard Worker
IsCounterRegistered(uint16_t counterUid) const252*89c4ff92SAndroid Build Coastguard Worker bool ProfilingService::IsCounterRegistered(uint16_t counterUid) const
253*89c4ff92SAndroid Build Coastguard Worker {
254*89c4ff92SAndroid Build Coastguard Worker return m_CounterDirectory.IsCounterRegistered(counterUid);
255*89c4ff92SAndroid Build Coastguard Worker }
256*89c4ff92SAndroid Build Coastguard Worker
GetAbsoluteCounterValue(uint16_t counterUid) const257*89c4ff92SAndroid Build Coastguard Worker uint32_t ProfilingService::GetAbsoluteCounterValue(uint16_t counterUid) const
258*89c4ff92SAndroid Build Coastguard Worker {
259*89c4ff92SAndroid Build Coastguard Worker CheckCounterUid(counterUid);
260*89c4ff92SAndroid Build Coastguard Worker std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
261*89c4ff92SAndroid Build Coastguard Worker ARM_PIPE_ASSERT(counterValuePtr);
262*89c4ff92SAndroid Build Coastguard Worker return counterValuePtr->load(std::memory_order::memory_order_relaxed);
263*89c4ff92SAndroid Build Coastguard Worker }
264*89c4ff92SAndroid Build Coastguard Worker
GetDeltaCounterValue(uint16_t counterUid)265*89c4ff92SAndroid Build Coastguard Worker uint32_t ProfilingService::GetDeltaCounterValue(uint16_t counterUid)
266*89c4ff92SAndroid Build Coastguard Worker {
267*89c4ff92SAndroid Build Coastguard Worker CheckCounterUid(counterUid);
268*89c4ff92SAndroid Build Coastguard Worker std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
269*89c4ff92SAndroid Build Coastguard Worker ARM_PIPE_ASSERT(counterValuePtr);
270*89c4ff92SAndroid Build Coastguard Worker const uint32_t counterValue = counterValuePtr->load(std::memory_order::memory_order_relaxed);
271*89c4ff92SAndroid Build Coastguard Worker SubtractCounterValue(counterUid, counterValue);
272*89c4ff92SAndroid Build Coastguard Worker return counterValue;
273*89c4ff92SAndroid Build Coastguard Worker }
274*89c4ff92SAndroid Build Coastguard Worker
GetCounterMappings() const275*89c4ff92SAndroid Build Coastguard Worker const ICounterMappings& ProfilingService::GetCounterMappings() const
276*89c4ff92SAndroid Build Coastguard Worker {
277*89c4ff92SAndroid Build Coastguard Worker return m_CounterIdMap;
278*89c4ff92SAndroid Build Coastguard Worker }
279*89c4ff92SAndroid Build Coastguard Worker
GetCounterMappingRegistry()280*89c4ff92SAndroid Build Coastguard Worker IRegisterCounterMapping& ProfilingService::GetCounterMappingRegistry()
281*89c4ff92SAndroid Build Coastguard Worker {
282*89c4ff92SAndroid Build Coastguard Worker return m_CounterIdMap;
283*89c4ff92SAndroid Build Coastguard Worker }
284*89c4ff92SAndroid Build Coastguard Worker
IsCategoryRegistered(const std::string & categoryName) const285*89c4ff92SAndroid Build Coastguard Worker bool ProfilingService::IsCategoryRegistered(const std::string& categoryName) const
286*89c4ff92SAndroid Build Coastguard Worker {
287*89c4ff92SAndroid Build Coastguard Worker return m_CounterDirectory.IsCategoryRegistered(categoryName);
288*89c4ff92SAndroid Build Coastguard Worker }
289*89c4ff92SAndroid Build Coastguard Worker
IsCounterRegistered(const std::string & counterName) const290*89c4ff92SAndroid Build Coastguard Worker bool ProfilingService::IsCounterRegistered(const std::string& counterName) const
291*89c4ff92SAndroid Build Coastguard Worker {
292*89c4ff92SAndroid Build Coastguard Worker return m_CounterDirectory.IsCounterRegistered(counterName);
293*89c4ff92SAndroid Build Coastguard Worker }
294*89c4ff92SAndroid Build Coastguard Worker
GetCaptureData()295*89c4ff92SAndroid Build Coastguard Worker CaptureData ProfilingService::GetCaptureData()
296*89c4ff92SAndroid Build Coastguard Worker {
297*89c4ff92SAndroid Build Coastguard Worker return m_Holder.GetCaptureData();
298*89c4ff92SAndroid Build Coastguard Worker }
299*89c4ff92SAndroid Build Coastguard Worker
SetCaptureData(uint32_t capturePeriod,const std::vector<uint16_t> & counterIds,const std::set<std::string> & activeBackends)300*89c4ff92SAndroid Build Coastguard Worker void ProfilingService::SetCaptureData(uint32_t capturePeriod,
301*89c4ff92SAndroid Build Coastguard Worker const std::vector<uint16_t>& counterIds,
302*89c4ff92SAndroid Build Coastguard Worker const std::set<std::string>& activeBackends)
303*89c4ff92SAndroid Build Coastguard Worker {
304*89c4ff92SAndroid Build Coastguard Worker m_Holder.SetCaptureData(capturePeriod, counterIds, activeBackends);
305*89c4ff92SAndroid Build Coastguard Worker }
306*89c4ff92SAndroid Build Coastguard Worker
SetCounterValue(uint16_t counterUid,uint32_t value)307*89c4ff92SAndroid Build Coastguard Worker void ProfilingService::SetCounterValue(uint16_t counterUid, uint32_t value)
308*89c4ff92SAndroid Build Coastguard Worker {
309*89c4ff92SAndroid Build Coastguard Worker CheckCounterUid(counterUid);
310*89c4ff92SAndroid Build Coastguard Worker std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
311*89c4ff92SAndroid Build Coastguard Worker ARM_PIPE_ASSERT(counterValuePtr);
312*89c4ff92SAndroid Build Coastguard Worker counterValuePtr->store(value, std::memory_order::memory_order_relaxed);
313*89c4ff92SAndroid Build Coastguard Worker }
314*89c4ff92SAndroid Build Coastguard Worker
AddCounterValue(uint16_t counterUid,uint32_t value)315*89c4ff92SAndroid Build Coastguard Worker uint32_t ProfilingService::AddCounterValue(uint16_t counterUid, uint32_t value)
316*89c4ff92SAndroid Build Coastguard Worker {
317*89c4ff92SAndroid Build Coastguard Worker CheckCounterUid(counterUid);
318*89c4ff92SAndroid Build Coastguard Worker std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
319*89c4ff92SAndroid Build Coastguard Worker ARM_PIPE_ASSERT(counterValuePtr);
320*89c4ff92SAndroid Build Coastguard Worker return counterValuePtr->fetch_add(value, std::memory_order::memory_order_relaxed);
321*89c4ff92SAndroid Build Coastguard Worker }
322*89c4ff92SAndroid Build Coastguard Worker
SubtractCounterValue(uint16_t counterUid,uint32_t value)323*89c4ff92SAndroid Build Coastguard Worker uint32_t ProfilingService::SubtractCounterValue(uint16_t counterUid, uint32_t value)
324*89c4ff92SAndroid Build Coastguard Worker {
325*89c4ff92SAndroid Build Coastguard Worker CheckCounterUid(counterUid);
326*89c4ff92SAndroid Build Coastguard Worker std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
327*89c4ff92SAndroid Build Coastguard Worker ARM_PIPE_ASSERT(counterValuePtr);
328*89c4ff92SAndroid Build Coastguard Worker return counterValuePtr->fetch_sub(value, std::memory_order::memory_order_relaxed);
329*89c4ff92SAndroid Build Coastguard Worker }
330*89c4ff92SAndroid Build Coastguard Worker
IncrementCounterValue(uint16_t counterUid)331*89c4ff92SAndroid Build Coastguard Worker uint32_t ProfilingService::IncrementCounterValue(uint16_t counterUid)
332*89c4ff92SAndroid Build Coastguard Worker {
333*89c4ff92SAndroid Build Coastguard Worker CheckCounterUid(counterUid);
334*89c4ff92SAndroid Build Coastguard Worker std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
335*89c4ff92SAndroid Build Coastguard Worker ARM_PIPE_ASSERT(counterValuePtr);
336*89c4ff92SAndroid Build Coastguard Worker return counterValuePtr->operator++(std::memory_order::memory_order_relaxed);
337*89c4ff92SAndroid Build Coastguard Worker }
338*89c4ff92SAndroid Build Coastguard Worker
GetSendTimelinePacket() const339*89c4ff92SAndroid Build Coastguard Worker std::unique_ptr<ISendTimelinePacket> ProfilingService::GetSendTimelinePacket() const
340*89c4ff92SAndroid Build Coastguard Worker {
341*89c4ff92SAndroid Build Coastguard Worker return m_TimelinePacketWriterFactory.GetSendTimelinePacket();
342*89c4ff92SAndroid Build Coastguard Worker }
343*89c4ff92SAndroid Build Coastguard Worker
Initialize()344*89c4ff92SAndroid Build Coastguard Worker void ProfilingService::Initialize()
345*89c4ff92SAndroid Build Coastguard Worker {
346*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
347*89c4ff92SAndroid Build Coastguard Worker m_Initialiser.InitialiseProfilingService(*this);
348*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
349*89c4ff92SAndroid Build Coastguard Worker }
350*89c4ff92SAndroid Build Coastguard Worker
InitializeCounterValue(uint16_t counterUid)351*89c4ff92SAndroid Build Coastguard Worker void ProfilingService::InitializeCounterValue(uint16_t counterUid)
352*89c4ff92SAndroid Build Coastguard Worker {
353*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
354*89c4ff92SAndroid Build Coastguard Worker // Increase the size of the counter index if necessary
355*89c4ff92SAndroid Build Coastguard Worker if (counterUid >= m_CounterIndex.size())
356*89c4ff92SAndroid Build Coastguard Worker {
357*89c4ff92SAndroid Build Coastguard Worker m_CounterIndex.resize(arm::pipe::numeric_cast<size_t>(counterUid) + 1);
358*89c4ff92SAndroid Build Coastguard Worker }
359*89c4ff92SAndroid Build Coastguard Worker
360*89c4ff92SAndroid Build Coastguard Worker // Create a new atomic counter and add it to the list
361*89c4ff92SAndroid Build Coastguard Worker m_CounterValues.emplace_back(0);
362*89c4ff92SAndroid Build Coastguard Worker
363*89c4ff92SAndroid Build Coastguard Worker // Register the new counter to the counter index for quick access
364*89c4ff92SAndroid Build Coastguard Worker std::atomic<uint32_t>* counterValuePtr = &(m_CounterValues.back());
365*89c4ff92SAndroid Build Coastguard Worker m_CounterIndex.at(counterUid) = counterValuePtr;
366*89c4ff92SAndroid Build Coastguard Worker #else
367*89c4ff92SAndroid Build Coastguard Worker IgnoreUnused(counterUid);
368*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
369*89c4ff92SAndroid Build Coastguard Worker }
370*89c4ff92SAndroid Build Coastguard Worker
Reset()371*89c4ff92SAndroid Build Coastguard Worker void ProfilingService::Reset()
372*89c4ff92SAndroid Build Coastguard Worker {
373*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
374*89c4ff92SAndroid Build Coastguard Worker // Stop the profiling service...
375*89c4ff92SAndroid Build Coastguard Worker Stop();
376*89c4ff92SAndroid Build Coastguard Worker
377*89c4ff92SAndroid Build Coastguard Worker // ...then delete all the counter data and configuration...
378*89c4ff92SAndroid Build Coastguard Worker m_CounterIndex.clear();
379*89c4ff92SAndroid Build Coastguard Worker m_CounterValues.clear();
380*89c4ff92SAndroid Build Coastguard Worker m_CounterDirectory.Clear();
381*89c4ff92SAndroid Build Coastguard Worker m_CounterIdMap.Reset();
382*89c4ff92SAndroid Build Coastguard Worker m_BufferManager.Reset();
383*89c4ff92SAndroid Build Coastguard Worker
384*89c4ff92SAndroid Build Coastguard Worker // ...finally reset the profiling state machine
385*89c4ff92SAndroid Build Coastguard Worker m_StateMachine.Reset();
386*89c4ff92SAndroid Build Coastguard Worker m_BackendProfilingContexts.clear();
387*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
388*89c4ff92SAndroid Build Coastguard Worker }
389*89c4ff92SAndroid Build Coastguard Worker
Stop()390*89c4ff92SAndroid Build Coastguard Worker void ProfilingService::Stop()
391*89c4ff92SAndroid Build Coastguard Worker {
392*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
393*89c4ff92SAndroid Build Coastguard Worker { // only lock when we are updating the inference completed variable
394*89c4ff92SAndroid Build Coastguard Worker std::unique_lock<std::mutex> lck(m_ServiceActiveMutex);
395*89c4ff92SAndroid Build Coastguard Worker m_ServiceActive = false;
396*89c4ff92SAndroid Build Coastguard Worker }
397*89c4ff92SAndroid Build Coastguard Worker // The order in which we reset/stop the components is not trivial!
398*89c4ff92SAndroid Build Coastguard Worker // First stop the producing threads
399*89c4ff92SAndroid Build Coastguard Worker // Command Handler first as it is responsible for launching then Periodic Counter capture thread
400*89c4ff92SAndroid Build Coastguard Worker m_CommandHandler.Stop();
401*89c4ff92SAndroid Build Coastguard Worker m_PeriodicCounterCapture.Stop();
402*89c4ff92SAndroid Build Coastguard Worker // The the consuming thread
403*89c4ff92SAndroid Build Coastguard Worker m_SendThread.Stop(false);
404*89c4ff92SAndroid Build Coastguard Worker
405*89c4ff92SAndroid Build Coastguard Worker // ...then close and destroy the profiling connection...
406*89c4ff92SAndroid Build Coastguard Worker if (m_ProfilingConnection != nullptr && m_ProfilingConnection->IsOpen())
407*89c4ff92SAndroid Build Coastguard Worker {
408*89c4ff92SAndroid Build Coastguard Worker m_ProfilingConnection->Close();
409*89c4ff92SAndroid Build Coastguard Worker }
410*89c4ff92SAndroid Build Coastguard Worker m_ProfilingConnection.reset();
411*89c4ff92SAndroid Build Coastguard Worker
412*89c4ff92SAndroid Build Coastguard Worker // ...then move to the "NotConnected" state
413*89c4ff92SAndroid Build Coastguard Worker m_StateMachine.TransitionToState(ProfilingState::NotConnected);
414*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
415*89c4ff92SAndroid Build Coastguard Worker }
416*89c4ff92SAndroid Build Coastguard Worker
CheckCounterUid(uint16_t counterUid) const417*89c4ff92SAndroid Build Coastguard Worker inline void ProfilingService::CheckCounterUid(uint16_t counterUid) const
418*89c4ff92SAndroid Build Coastguard Worker {
419*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
420*89c4ff92SAndroid Build Coastguard Worker if (!IsCounterRegistered(counterUid))
421*89c4ff92SAndroid Build Coastguard Worker {
422*89c4ff92SAndroid Build Coastguard Worker throw arm::pipe::InvalidArgumentException(fmt::format("Counter UID {} is not registered", counterUid));
423*89c4ff92SAndroid Build Coastguard Worker }
424*89c4ff92SAndroid Build Coastguard Worker #else
425*89c4ff92SAndroid Build Coastguard Worker IgnoreUnused(counterUid);
426*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
427*89c4ff92SAndroid Build Coastguard Worker }
428*89c4ff92SAndroid Build Coastguard Worker
NotifyBackendsForTimelineReporting()429*89c4ff92SAndroid Build Coastguard Worker void ProfilingService::NotifyBackendsForTimelineReporting()
430*89c4ff92SAndroid Build Coastguard Worker {
431*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
432*89c4ff92SAndroid Build Coastguard Worker BackendProfilingContext::iterator it = m_BackendProfilingContexts.begin();
433*89c4ff92SAndroid Build Coastguard Worker while (it != m_BackendProfilingContexts.end())
434*89c4ff92SAndroid Build Coastguard Worker {
435*89c4ff92SAndroid Build Coastguard Worker auto& backendProfilingContext = it->second;
436*89c4ff92SAndroid Build Coastguard Worker backendProfilingContext->EnableTimelineReporting(m_TimelineReporting);
437*89c4ff92SAndroid Build Coastguard Worker // Increment the Iterator to point to next entry
438*89c4ff92SAndroid Build Coastguard Worker it++;
439*89c4ff92SAndroid Build Coastguard Worker }
440*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
441*89c4ff92SAndroid Build Coastguard Worker }
442*89c4ff92SAndroid Build Coastguard Worker
NotifyProfilingServiceActive()443*89c4ff92SAndroid Build Coastguard Worker void ProfilingService::NotifyProfilingServiceActive()
444*89c4ff92SAndroid Build Coastguard Worker {
445*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
446*89c4ff92SAndroid Build Coastguard Worker { // only lock when we are updating the inference completed variable
447*89c4ff92SAndroid Build Coastguard Worker std::unique_lock<std::mutex> lck(m_ServiceActiveMutex);
448*89c4ff92SAndroid Build Coastguard Worker m_ServiceActive = true;
449*89c4ff92SAndroid Build Coastguard Worker }
450*89c4ff92SAndroid Build Coastguard Worker m_ServiceActiveConditionVariable.notify_one();
451*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
452*89c4ff92SAndroid Build Coastguard Worker }
453*89c4ff92SAndroid Build Coastguard Worker
WaitForProfilingServiceActivation(unsigned int timeout)454*89c4ff92SAndroid Build Coastguard Worker void ProfilingService::WaitForProfilingServiceActivation(unsigned int timeout)
455*89c4ff92SAndroid Build Coastguard Worker {
456*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
457*89c4ff92SAndroid Build Coastguard Worker std::unique_lock<std::mutex> lck(m_ServiceActiveMutex);
458*89c4ff92SAndroid Build Coastguard Worker
459*89c4ff92SAndroid Build Coastguard Worker auto start = std::chrono::high_resolution_clock::now();
460*89c4ff92SAndroid Build Coastguard Worker // Here we we will go back to sleep after a spurious wake up if
461*89c4ff92SAndroid Build Coastguard Worker // m_InferenceCompleted is not yet true.
462*89c4ff92SAndroid Build Coastguard Worker if (!m_ServiceActiveConditionVariable.wait_for(lck,
463*89c4ff92SAndroid Build Coastguard Worker std::chrono::milliseconds(timeout),
464*89c4ff92SAndroid Build Coastguard Worker [&]{return m_ServiceActive == true;}))
465*89c4ff92SAndroid Build Coastguard Worker {
466*89c4ff92SAndroid Build Coastguard Worker if (m_ServiceActive == true)
467*89c4ff92SAndroid Build Coastguard Worker {
468*89c4ff92SAndroid Build Coastguard Worker return;
469*89c4ff92SAndroid Build Coastguard Worker }
470*89c4ff92SAndroid Build Coastguard Worker auto finish = std::chrono::high_resolution_clock::now();
471*89c4ff92SAndroid Build Coastguard Worker std::chrono::duration<double, std::milli> elapsed = finish - start;
472*89c4ff92SAndroid Build Coastguard Worker std::stringstream ss;
473*89c4ff92SAndroid Build Coastguard Worker ss << "Timed out waiting on profiling service activation for " << elapsed.count() << " ms";
474*89c4ff92SAndroid Build Coastguard Worker ARM_PIPE_LOG(warning) << ss.str();
475*89c4ff92SAndroid Build Coastguard Worker }
476*89c4ff92SAndroid Build Coastguard Worker #else
477*89c4ff92SAndroid Build Coastguard Worker IgnoreUnused(timeout);
478*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
479*89c4ff92SAndroid Build Coastguard Worker }
480*89c4ff92SAndroid Build Coastguard Worker
~ProfilingService()481*89c4ff92SAndroid Build Coastguard Worker ProfilingService::~ProfilingService()
482*89c4ff92SAndroid Build Coastguard Worker {
483*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
484*89c4ff92SAndroid Build Coastguard Worker Stop();
485*89c4ff92SAndroid Build Coastguard Worker #endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
486*89c4ff92SAndroid Build Coastguard Worker }
487*89c4ff92SAndroid Build Coastguard Worker
488*89c4ff92SAndroid Build Coastguard Worker } // namespace pipe
489*89c4ff92SAndroid Build Coastguard Worker
490*89c4ff92SAndroid Build Coastguard Worker } // namespace arm
491