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