1*89c4ff92SAndroid Build Coastguard Worker //
2*89c4ff92SAndroid Build Coastguard Worker // Copyright © 2019 Arm Ltd. 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 "PeriodicCounterCapture.hpp"
7*89c4ff92SAndroid Build Coastguard Worker
8*89c4ff92SAndroid Build Coastguard Worker #include <common/include/Logging.hpp>
9*89c4ff92SAndroid Build Coastguard Worker
10*89c4ff92SAndroid Build Coastguard Worker #include <iostream>
11*89c4ff92SAndroid Build Coastguard Worker
12*89c4ff92SAndroid Build Coastguard Worker namespace arm
13*89c4ff92SAndroid Build Coastguard Worker {
14*89c4ff92SAndroid Build Coastguard Worker
15*89c4ff92SAndroid Build Coastguard Worker namespace pipe
16*89c4ff92SAndroid Build Coastguard Worker {
17*89c4ff92SAndroid Build Coastguard Worker
Start()18*89c4ff92SAndroid Build Coastguard Worker void PeriodicCounterCapture::Start()
19*89c4ff92SAndroid Build Coastguard Worker {
20*89c4ff92SAndroid Build Coastguard Worker // Check if the capture thread is already running
21*89c4ff92SAndroid Build Coastguard Worker if (m_IsRunning)
22*89c4ff92SAndroid Build Coastguard Worker {
23*89c4ff92SAndroid Build Coastguard Worker // The capture thread is already running
24*89c4ff92SAndroid Build Coastguard Worker return;
25*89c4ff92SAndroid Build Coastguard Worker }
26*89c4ff92SAndroid Build Coastguard Worker
27*89c4ff92SAndroid Build Coastguard Worker // Mark the capture thread as running
28*89c4ff92SAndroid Build Coastguard Worker m_IsRunning = true;
29*89c4ff92SAndroid Build Coastguard Worker
30*89c4ff92SAndroid Build Coastguard Worker // Keep the capture procedure going until the capture thread is signalled to stop
31*89c4ff92SAndroid Build Coastguard Worker m_KeepRunning.store(true);
32*89c4ff92SAndroid Build Coastguard Worker
33*89c4ff92SAndroid Build Coastguard Worker // Start the new capture thread.
34*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
35*89c4ff92SAndroid Build Coastguard Worker m_PeriodCaptureThread = std::thread(&PeriodicCounterCapture::Capture, this, std::ref(m_ReadCounterValues));
36*89c4ff92SAndroid Build Coastguard Worker #endif
37*89c4ff92SAndroid Build Coastguard Worker }
38*89c4ff92SAndroid Build Coastguard Worker
Stop()39*89c4ff92SAndroid Build Coastguard Worker void PeriodicCounterCapture::Stop()
40*89c4ff92SAndroid Build Coastguard Worker {
41*89c4ff92SAndroid Build Coastguard Worker // Signal the capture thread to stop
42*89c4ff92SAndroid Build Coastguard Worker m_KeepRunning.store(false);
43*89c4ff92SAndroid Build Coastguard Worker
44*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
45*89c4ff92SAndroid Build Coastguard Worker // Check that the capture thread is running
46*89c4ff92SAndroid Build Coastguard Worker if (m_PeriodCaptureThread.joinable())
47*89c4ff92SAndroid Build Coastguard Worker {
48*89c4ff92SAndroid Build Coastguard Worker // Wait for the capture thread to complete operations
49*89c4ff92SAndroid Build Coastguard Worker m_PeriodCaptureThread.join();
50*89c4ff92SAndroid Build Coastguard Worker }
51*89c4ff92SAndroid Build Coastguard Worker #endif
52*89c4ff92SAndroid Build Coastguard Worker
53*89c4ff92SAndroid Build Coastguard Worker // Mark the capture thread as not running
54*89c4ff92SAndroid Build Coastguard Worker m_IsRunning = false;
55*89c4ff92SAndroid Build Coastguard Worker }
56*89c4ff92SAndroid Build Coastguard Worker
ReadCaptureData()57*89c4ff92SAndroid Build Coastguard Worker CaptureData PeriodicCounterCapture::ReadCaptureData()
58*89c4ff92SAndroid Build Coastguard Worker {
59*89c4ff92SAndroid Build Coastguard Worker return m_CaptureDataHolder.GetCaptureData();
60*89c4ff92SAndroid Build Coastguard Worker }
61*89c4ff92SAndroid Build Coastguard Worker
DispatchPeriodicCounterCapturePacket(const std::string & backendId,const std::vector<Timestamp> & timestampValues)62*89c4ff92SAndroid Build Coastguard Worker void PeriodicCounterCapture::DispatchPeriodicCounterCapturePacket(
63*89c4ff92SAndroid Build Coastguard Worker const std::string& backendId, const std::vector<Timestamp>& timestampValues)
64*89c4ff92SAndroid Build Coastguard Worker {
65*89c4ff92SAndroid Build Coastguard Worker // Report counter values
66*89c4ff92SAndroid Build Coastguard Worker for (const auto& timestampInfo : timestampValues)
67*89c4ff92SAndroid Build Coastguard Worker {
68*89c4ff92SAndroid Build Coastguard Worker std::vector<CounterValue> backendCounterValues = timestampInfo.counterValues;
69*89c4ff92SAndroid Build Coastguard Worker for_each(backendCounterValues.begin(), backendCounterValues.end(), [&](CounterValue& backendCounterValue)
70*89c4ff92SAndroid Build Coastguard Worker {
71*89c4ff92SAndroid Build Coastguard Worker // translate the counterId to globalCounterId
72*89c4ff92SAndroid Build Coastguard Worker backendCounterValue.counterId = m_CounterIdMap.GetGlobalId(backendCounterValue.counterId, backendId);
73*89c4ff92SAndroid Build Coastguard Worker });
74*89c4ff92SAndroid Build Coastguard Worker
75*89c4ff92SAndroid Build Coastguard Worker // Send Periodic Counter Capture Packet for the Timestamp
76*89c4ff92SAndroid Build Coastguard Worker m_SendCounterPacket.SendPeriodicCounterCapturePacket(timestampInfo.timestamp, backendCounterValues);
77*89c4ff92SAndroid Build Coastguard Worker }
78*89c4ff92SAndroid Build Coastguard Worker }
79*89c4ff92SAndroid Build Coastguard Worker
Capture(IReadCounterValues & readCounterValues)80*89c4ff92SAndroid Build Coastguard Worker void PeriodicCounterCapture::Capture(IReadCounterValues& readCounterValues)
81*89c4ff92SAndroid Build Coastguard Worker {
82*89c4ff92SAndroid Build Coastguard Worker do
83*89c4ff92SAndroid Build Coastguard Worker {
84*89c4ff92SAndroid Build Coastguard Worker // Check if the current capture data indicates that there's data capture
85*89c4ff92SAndroid Build Coastguard Worker auto currentCaptureData = ReadCaptureData();
86*89c4ff92SAndroid Build Coastguard Worker const std::vector<uint16_t>& counterIds = currentCaptureData.GetCounterIds();
87*89c4ff92SAndroid Build Coastguard Worker const uint32_t capturePeriod = currentCaptureData.GetCapturePeriod();
88*89c4ff92SAndroid Build Coastguard Worker
89*89c4ff92SAndroid Build Coastguard Worker if (capturePeriod == 0)
90*89c4ff92SAndroid Build Coastguard Worker {
91*89c4ff92SAndroid Build Coastguard Worker // No data capture, wait the indicated capture period (milliseconds), if it is not zero
92*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
93*89c4ff92SAndroid Build Coastguard Worker std::this_thread::sleep_for(std::chrono::milliseconds(50u));
94*89c4ff92SAndroid Build Coastguard Worker #endif
95*89c4ff92SAndroid Build Coastguard Worker continue;
96*89c4ff92SAndroid Build Coastguard Worker }
97*89c4ff92SAndroid Build Coastguard Worker
98*89c4ff92SAndroid Build Coastguard Worker if(counterIds.size() != 0)
99*89c4ff92SAndroid Build Coastguard Worker {
100*89c4ff92SAndroid Build Coastguard Worker std::vector<CounterValue> counterValues;
101*89c4ff92SAndroid Build Coastguard Worker
102*89c4ff92SAndroid Build Coastguard Worker auto numCounters = counterIds.size();
103*89c4ff92SAndroid Build Coastguard Worker counterValues.reserve(numCounters);
104*89c4ff92SAndroid Build Coastguard Worker
105*89c4ff92SAndroid Build Coastguard Worker // Create a vector of pairs of CounterIndexes and Values
106*89c4ff92SAndroid Build Coastguard Worker for (uint16_t index = 0; index < numCounters; ++index)
107*89c4ff92SAndroid Build Coastguard Worker {
108*89c4ff92SAndroid Build Coastguard Worker auto requestedId = counterIds[index];
109*89c4ff92SAndroid Build Coastguard Worker uint32_t counterValue = 0;
110*89c4ff92SAndroid Build Coastguard Worker try
111*89c4ff92SAndroid Build Coastguard Worker {
112*89c4ff92SAndroid Build Coastguard Worker counterValue = readCounterValues.GetDeltaCounterValue(requestedId);
113*89c4ff92SAndroid Build Coastguard Worker }
114*89c4ff92SAndroid Build Coastguard Worker catch (const arm::pipe::ProfilingException& e)
115*89c4ff92SAndroid Build Coastguard Worker {
116*89c4ff92SAndroid Build Coastguard Worker // Report the error and continue
117*89c4ff92SAndroid Build Coastguard Worker ARM_PIPE_LOG(warning) << "An error has occurred when getting a counter value: "
118*89c4ff92SAndroid Build Coastguard Worker << e.what();
119*89c4ff92SAndroid Build Coastguard Worker continue;
120*89c4ff92SAndroid Build Coastguard Worker }
121*89c4ff92SAndroid Build Coastguard Worker
122*89c4ff92SAndroid Build Coastguard Worker counterValues.emplace_back(CounterValue {requestedId, counterValue });
123*89c4ff92SAndroid Build Coastguard Worker }
124*89c4ff92SAndroid Build Coastguard Worker
125*89c4ff92SAndroid Build Coastguard Worker // Send Periodic Counter Capture Packet for the Timestamp
126*89c4ff92SAndroid Build Coastguard Worker m_SendCounterPacket.SendPeriodicCounterCapturePacket(GetTimestamp(), counterValues);
127*89c4ff92SAndroid Build Coastguard Worker }
128*89c4ff92SAndroid Build Coastguard Worker
129*89c4ff92SAndroid Build Coastguard Worker // Report counter values for each active backend
130*89c4ff92SAndroid Build Coastguard Worker auto activeBackends = currentCaptureData.GetActiveBackends();
131*89c4ff92SAndroid Build Coastguard Worker for_each(activeBackends.begin(), activeBackends.end(), [&](const std::string& backendId)
132*89c4ff92SAndroid Build Coastguard Worker {
133*89c4ff92SAndroid Build Coastguard Worker DispatchPeriodicCounterCapturePacket(
134*89c4ff92SAndroid Build Coastguard Worker backendId, m_BackendProfilingContexts.at(backendId)->ReportCounterValues());
135*89c4ff92SAndroid Build Coastguard Worker });
136*89c4ff92SAndroid Build Coastguard Worker
137*89c4ff92SAndroid Build Coastguard Worker // Wait the indicated capture period (microseconds)
138*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
139*89c4ff92SAndroid Build Coastguard Worker std::this_thread::sleep_for(std::chrono::microseconds(capturePeriod));
140*89c4ff92SAndroid Build Coastguard Worker #endif
141*89c4ff92SAndroid Build Coastguard Worker }
142*89c4ff92SAndroid Build Coastguard Worker while (m_KeepRunning.load());
143*89c4ff92SAndroid Build Coastguard Worker }
144*89c4ff92SAndroid Build Coastguard Worker
145*89c4ff92SAndroid Build Coastguard Worker } // namespace pipe
146*89c4ff92SAndroid Build Coastguard Worker
147*89c4ff92SAndroid Build Coastguard Worker } // namespace arm
148