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