blob: ae2aa0b94c9e1a64a725998b5ecfbb0ea320aecf [file] [log] [blame]
Ferran Balaguer1b941722019-08-28 16:57:18 +01001//
Jim Flynnbbfe6032020-07-20 16:57:44 +01002// Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
Ferran Balaguer1b941722019-08-28 16:57:18 +01003// SPDX-License-Identifier: MIT
4//
5
6#include "PeriodicCounterSelectionCommandHandler.hpp"
7#include "ProfilingUtils.hpp"
8
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00009#include <armnn/profiling/ProfilingOptions.hpp>
Matthew Sloyan371b70e2020-09-11 10:14:57 +010010#include <armnn/utility/NumericCast.hpp>
11
Jan Eilers156113c2020-09-09 19:11:16 +010012#include <fmt/format.h>
Matteo Martincighe8485382019-10-10 14:08:21 +010013
14#include <vector>
Ferran Balaguer1b941722019-08-28 16:57:18 +010015
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000016namespace arm
Ferran Balaguer1b941722019-08-28 16:57:18 +010017{
18
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000019namespace pipe
Ferran Balaguer1b941722019-08-28 16:57:18 +010020{
21
Jim Flynnbbfe6032020-07-20 16:57:44 +010022void PeriodicCounterSelectionCommandHandler::ParseData(const arm::pipe::Packet& packet, CaptureData& captureData)
Ferran Balaguer1b941722019-08-28 16:57:18 +010023{
24 std::vector<uint16_t> counterIds;
Matthew Sloyan371b70e2020-09-11 10:14:57 +010025 uint32_t sizeOfUint32 = armnn::numeric_cast<uint32_t>(sizeof(uint32_t));
26 uint32_t sizeOfUint16 = armnn::numeric_cast<uint32_t>(sizeof(uint16_t));
Ferran Balaguer1b941722019-08-28 16:57:18 +010027 uint32_t offset = 0;
28
Matteo Martincighe8485382019-10-10 14:08:21 +010029 if (packet.GetLength() < 4)
Ferran Balaguer1b941722019-08-28 16:57:18 +010030 {
Matteo Martincighe8485382019-10-10 14:08:21 +010031 // Insufficient packet size
32 return;
33 }
34
35 // Parse the capture period
36 uint32_t capturePeriod = ReadUint32(packet.GetData(), offset);
37
38 // Set the capture period
39 captureData.SetCapturePeriod(capturePeriod);
40
41 // Parse the counter ids
42 unsigned int counters = (packet.GetLength() - 4) / 2;
43 if (counters > 0)
44 {
45 counterIds.reserve(counters);
46 offset += sizeOfUint32;
47 for (unsigned int i = 0; i < counters; ++i)
Ferran Balaguer1b941722019-08-28 16:57:18 +010048 {
Matteo Martincighe8485382019-10-10 14:08:21 +010049 // Parse the counter id
50 uint16_t counterId = ReadUint16(packet.GetData(), offset);
51 counterIds.emplace_back(counterId);
52 offset += sizeOfUint16;
Ferran Balaguer1b941722019-08-28 16:57:18 +010053 }
54 }
Matteo Martincighe8485382019-10-10 14:08:21 +010055
56 // Set the counter ids
57 captureData.SetCounterIds(counterIds);
Ferran Balaguer1b941722019-08-28 16:57:18 +010058}
59
Jim Flynnbbfe6032020-07-20 16:57:44 +010060void PeriodicCounterSelectionCommandHandler::operator()(const arm::pipe::Packet& packet)
Ferran Balaguer1b941722019-08-28 16:57:18 +010061{
Matteo Martincighe8485382019-10-10 14:08:21 +010062 ProfilingState currentState = m_StateMachine.GetCurrentState();
63 switch (currentState)
64 {
65 case ProfilingState::Uninitialised:
66 case ProfilingState::NotConnected:
67 case ProfilingState::WaitingForAck:
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000068 throw armnn::RuntimeException(fmt::format("Periodic Counter Selection Command Handler invoked while in "
Jan Eilers156113c2020-09-09 19:11:16 +010069 "an wrong state: {}",
70 GetProfilingStateName(currentState)));
Matteo Martincighe8485382019-10-10 14:08:21 +010071 case ProfilingState::Active:
72 {
73 // Process the packet
74 if (!(packet.GetPacketFamily() == 0u && packet.GetPacketId() == 4u))
75 {
Jan Eilers156113c2020-09-09 19:11:16 +010076 throw armnn::InvalidArgumentException(fmt::format("Expected Packet family = 0, id = 4 but "
77 "received family = {}, id = {}",
78 packet.GetPacketFamily(),
79 packet.GetPacketId()));
Matteo Martincighe8485382019-10-10 14:08:21 +010080 }
Ferran Balaguer1b941722019-08-28 16:57:18 +010081
Matteo Martincighe8485382019-10-10 14:08:21 +010082 // Parse the packet to get the capture period and counter UIDs
83 CaptureData captureData;
84 ParseData(packet, captureData);
Ferran Balaguer1b941722019-08-28 16:57:18 +010085
Matteo Martincighe8485382019-10-10 14:08:21 +010086 // Get the capture data
Colm Donelan02705242019-11-14 14:19:07 +000087 uint32_t capturePeriod = captureData.GetCapturePeriod();
88 // Validate that the capture period is within the acceptable range.
Jim Flynn4c9ed1d2022-01-23 23:57:20 +000089 if (capturePeriod > 0 && capturePeriod < arm::pipe::LOWEST_CAPTURE_PERIOD)
Colm Donelan02705242019-11-14 14:19:07 +000090 {
Jim Flynn4c9ed1d2022-01-23 23:57:20 +000091 capturePeriod = arm::pipe::LOWEST_CAPTURE_PERIOD;
Colm Donelan02705242019-11-14 14:19:07 +000092 }
Matteo Martincighe8485382019-10-10 14:08:21 +010093 const std::vector<uint16_t>& counterIds = captureData.GetCounterIds();
Ferran Balaguer1b941722019-08-28 16:57:18 +010094
Matteo Martincighe8485382019-10-10 14:08:21 +010095 // Check whether the selected counter UIDs are valid
96 std::vector<uint16_t> validCounterIds;
97 for (uint16_t counterId : counterIds)
98 {
99 // Check whether the counter is registered
100 if (!m_ReadCounterValues.IsCounterRegistered(counterId))
101 {
102 // Invalid counter UID, ignore it and continue
103 continue;
104 }
Matteo Martincighe8485382019-10-10 14:08:21 +0100105 // The counter is valid
Finn Williams032bc742020-02-12 11:02:34 +0000106 validCounterIds.emplace_back(counterId);
Matteo Martincighe8485382019-10-10 14:08:21 +0100107 }
Ferran Balaguer1b941722019-08-28 16:57:18 +0100108
Finn Williams032bc742020-02-12 11:02:34 +0000109 std::sort(validCounterIds.begin(), validCounterIds.end());
110
111 auto backendIdStart = std::find_if(validCounterIds.begin(), validCounterIds.end(), [&](uint16_t& counterId)
112 {
113 return counterId > m_MaxArmCounterId;
114 });
115
116 std::set<armnn::BackendId> activeBackends;
117 std::set<uint16_t> backendCounterIds = std::set<uint16_t>(backendIdStart, validCounterIds.end());
118
119 if (m_BackendCounterMap.size() != 0)
120 {
121 std::set<uint16_t> newCounterIds;
122 std::set<uint16_t> unusedCounterIds;
123
124 // Get any backend counter ids that is in backendCounterIds but not in m_PrevBackendCounterIds
125 std::set_difference(backendCounterIds.begin(), backendCounterIds.end(),
126 m_PrevBackendCounterIds.begin(), m_PrevBackendCounterIds.end(),
127 std::inserter(newCounterIds, newCounterIds.begin()));
128
129 // Get any backend counter ids that is in m_PrevBackendCounterIds but not in backendCounterIds
130 std::set_difference(m_PrevBackendCounterIds.begin(), m_PrevBackendCounterIds.end(),
131 backendCounterIds.begin(), backendCounterIds.end(),
132 std::inserter(unusedCounterIds, unusedCounterIds.begin()));
133
134 activeBackends = ProcessBackendCounterIds(capturePeriod, newCounterIds, unusedCounterIds);
135 }
136 else
137 {
138 activeBackends = ProcessBackendCounterIds(capturePeriod, backendCounterIds, {});
139 }
140
141 // save the new backend counter ids for next time
142 m_PrevBackendCounterIds = backendCounterIds;
143
Finn Williams032bc742020-02-12 11:02:34 +0000144 // Set the capture data with only the valid armnn counter UIDs
145 m_CaptureDataHolder.SetCaptureData(capturePeriod, {validCounterIds.begin(), backendIdStart}, activeBackends);
Matteo Martincighe8485382019-10-10 14:08:21 +0100146
147 // Echo back the Periodic Counter Selection packet to the Counter Stream Buffer
148 m_SendCounterPacket.SendPeriodicCounterSelectionPacket(capturePeriod, validCounterIds);
149
Finn Williamsf4d59a62019-10-14 15:55:18 +0100150 if (capturePeriod == 0 || validCounterIds.empty())
151 {
152 // No data capture stop the thread
153 m_PeriodicCounterCapture.Stop();
154 }
155 else
156 {
157 // Start the Period Counter Capture thread (if not running already)
158 m_PeriodicCounterCapture.Start();
159 }
Matteo Martincighe8485382019-10-10 14:08:21 +0100160
161 break;
162 }
163 default:
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000164 throw armnn::RuntimeException(fmt::format("Unknown profiling service state: {}",
Jan Eilers156113c2020-09-09 19:11:16 +0100165 static_cast<int>(currentState)));
Matteo Martincighe8485382019-10-10 14:08:21 +0100166 }
Ferran Balaguer1b941722019-08-28 16:57:18 +0100167}
168
Finn Williams032bc742020-02-12 11:02:34 +0000169std::set<armnn::BackendId> PeriodicCounterSelectionCommandHandler::ProcessBackendCounterIds(
Rob Hughesb98032f2020-04-24 11:41:34 +0100170 const uint32_t capturePeriod,
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100171 const std::set<uint16_t> newCounterIds,
172 const std::set<uint16_t> unusedCounterIds)
Finn Williams032bc742020-02-12 11:02:34 +0000173{
174 std::set<armnn::BackendId> changedBackends;
175 std::set<armnn::BackendId> activeBackends = m_CaptureDataHolder.GetCaptureData().GetActiveBackends();
176
177 for (uint16_t counterId : newCounterIds)
178 {
179 auto backendId = m_CounterIdMap.GetBackendId(counterId);
180 m_BackendCounterMap[backendId.second].emplace_back(backendId.first);
181 changedBackends.insert(backendId.second);
182 }
183 // Add any new backends to active backends
184 activeBackends.insert(changedBackends.begin(), changedBackends.end());
185
186 for (uint16_t counterId : unusedCounterIds)
187 {
188 auto backendId = m_CounterIdMap.GetBackendId(counterId);
189 std::vector<uint16_t>& backendCounters = m_BackendCounterMap[backendId.second];
190
191 backendCounters.erase(std::remove(backendCounters.begin(), backendCounters.end(), backendId.first));
192
193 if(backendCounters.size() == 0)
194 {
195 // If a backend has no counters associated with it we remove it from active backends and
196 // send a capture period of zero with an empty vector, this will deactivate all the backends counters
197 activeBackends.erase(backendId.second);
198 ActivateBackedCounters(backendId.second, 0, {});
199 }
200 else
201 {
202 changedBackends.insert(backendId.second);
203 }
204 }
205
206 // If the capture period remains the same we only need to update the backends who's counters have changed
207 if(capturePeriod == m_PrevCapturePeriod)
208 {
209 for (auto backend : changedBackends)
210 {
211 ActivateBackedCounters(backend, capturePeriod, m_BackendCounterMap[backend]);
212 }
213 }
214 // Otherwise update all the backends with the new capture period and any new/unused counters
215 else
216 {
217 for (auto backend : m_BackendCounterMap)
218 {
219 ActivateBackedCounters(backend.first, capturePeriod, backend.second);
220 }
221 if(capturePeriod == 0)
222 {
223 activeBackends = {};
224 }
225 m_PrevCapturePeriod = capturePeriod;
226 }
227
228 return activeBackends;
229}
230
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000231} // namespace pipe
Ferran Balaguer1b941722019-08-28 16:57:18 +0100232
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000233} // namespace arm