ArmNN
 20.02
GatordMockTests.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
8 #include <ProfilingService.hpp>
9 #include <GatordMockService.hpp>
12 
14 
15 #include <test/ProfilingMocks.hpp>
16 
17 #include <boost/cast.hpp>
18 #include <boost/test/test_tools.hpp>
19 #include <boost/test/unit_test_suite.hpp>
20 
21 BOOST_AUTO_TEST_SUITE(GatordMockTests)
22 
23 using namespace armnn;
24 using namespace std::this_thread; // sleep_for, sleep_until
25 using namespace std::chrono_literals;
26 
27 BOOST_AUTO_TEST_CASE(CounterCaptureHandlingTest)
28 {
29  using boost::numeric_cast;
30 
31  profiling::PacketVersionResolver packetVersionResolver;
32 
33  // Data with timestamp, counter idx & counter values
34  std::vector<std::pair<uint16_t, uint32_t>> indexValuePairs;
35  indexValuePairs.reserve(5);
36  indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t>(0, 100));
37  indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t>(1, 200));
38  indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t>(2, 300));
39  indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t>(3, 400));
40  indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t>(4, 500));
41 
42  // ((uint16_t (2 bytes) + uint32_t (4 bytes)) * 5) + word1 + word2
43  uint32_t dataLength = 38;
44 
45  // Simulate two different packets incoming 500 ms apart
46  uint64_t time = static_cast<uint64_t>(
47  std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch())
48  .count());
49 
50  uint64_t time2 = time + 5000;
51 
52  // UniqueData required for Packet class
53  std::unique_ptr<unsigned char[]> uniqueData1 = std::make_unique<unsigned char[]>(dataLength);
54  unsigned char* data1 = reinterpret_cast<unsigned char*>(uniqueData1.get());
55 
56  std::unique_ptr<unsigned char[]> uniqueData2 = std::make_unique<unsigned char[]>(dataLength);
57  unsigned char* data2 = reinterpret_cast<unsigned char*>(uniqueData2.get());
58 
59  uint32_t sizeOfUint64 = numeric_cast<uint32_t>(sizeof(uint64_t));
60  uint32_t sizeOfUint32 = numeric_cast<uint32_t>(sizeof(uint32_t));
61  uint32_t sizeOfUint16 = numeric_cast<uint32_t>(sizeof(uint16_t));
62  // Offset index to point to mem address
63  uint32_t offset = 0;
64 
65  profiling::WriteUint64(data1, offset, time);
66  offset += sizeOfUint64;
67  for (const auto& pair : indexValuePairs)
68  {
69  profiling::WriteUint16(data1, offset, pair.first);
70  offset += sizeOfUint16;
71  profiling::WriteUint32(data1, offset, pair.second);
72  offset += sizeOfUint32;
73  }
74 
75  offset = 0;
76 
77  profiling::WriteUint64(data2, offset, time2);
78  offset += sizeOfUint64;
79  for (const auto& pair : indexValuePairs)
80  {
81  profiling::WriteUint16(data2, offset, pair.first);
82  offset += sizeOfUint16;
83  profiling::WriteUint32(data2, offset, pair.second);
84  offset += sizeOfUint32;
85  }
86 
87  uint32_t headerWord1 = packetVersionResolver.ResolvePacketVersion(0, 4).GetEncodedValue();
88  // Create packet to send through to the command functor
89  profiling::Packet packet1(headerWord1, dataLength, uniqueData1);
90  profiling::Packet packet2(headerWord1, dataLength, uniqueData2);
91 
92  gatordmock::PeriodicCounterCaptureCommandHandler commandHandler(0, 4, headerWord1, true);
93 
94  // Simulate two separate packets coming in to calculate period
95  commandHandler(packet1);
96  commandHandler(packet2);
97 
98  BOOST_ASSERT(commandHandler.m_CurrentPeriodValue == 5000);
99 
100  for (size_t i = 0; i < commandHandler.m_CounterCaptureValues.m_Uids.size(); ++i)
101  {
102  BOOST_ASSERT(commandHandler.m_CounterCaptureValues.m_Uids[i] == i);
103  }
104 }
105 
106 BOOST_AUTO_TEST_CASE(GatorDMockEndToEnd)
107 {
108  // The purpose of this test is to setup both sides of the profiling service and get to the point of receiving
109  // performance data.
110 
111  //These variables are used to wait for the profiling service
112  uint32_t timeout = 2000;
113  uint32_t sleepTime = 50;
114  uint32_t timeSlept = 0;
115 
116  profiling::PacketVersionResolver packetVersionResolver;
117 
118  // Create the Command Handler Registry
120 
121  // Update with derived functors
122  gatordmock::StreamMetadataCommandHandler streamMetadataCommandHandler(
123  0, 0, packetVersionResolver.ResolvePacketVersion(0, 0).GetEncodedValue(), true);
124 
125  gatordmock::PeriodicCounterCaptureCommandHandler counterCaptureCommandHandler(
126  0, 4, packetVersionResolver.ResolvePacketVersion(0, 4).GetEncodedValue(), true);
127 
128  profiling::DirectoryCaptureCommandHandler directoryCaptureCommandHandler(
129  0, 2, packetVersionResolver.ResolvePacketVersion(0, 2).GetEncodedValue(), true);
130 
131  timelinedecoder::TimelineDirectoryCaptureCommandHandler timelineDirectoryCaptureCommandHandler(
132  1, 0, packetVersionResolver.ResolvePacketVersion(1, 0).GetEncodedValue(), true);
133 
134  // Register different derived functors
135  registry.RegisterFunctor(&streamMetadataCommandHandler);
136  registry.RegisterFunctor(&counterCaptureCommandHandler);
137  registry.RegisterFunctor(&directoryCaptureCommandHandler);
138  registry.RegisterFunctor(&timelineDirectoryCaptureCommandHandler);
139  // Setup the mock service to bind to the UDS.
140  std::string udsNamespace = "gatord_namespace";
141  gatordmock::GatordMockService mockService(registry, false);
142  mockService.OpenListeningSocket(udsNamespace);
143 
144  // Enable the profiling service.
146  options.m_EnableProfiling = true;
148  profilingService.ResetExternalProfilingOptions(options, true);
149 
150  // Bring the profiling service to the "WaitingForAck" state
152  profilingService.Update();
154  profilingService.Update();
155 
156  // Connect the profiling service to the mock Gatord.
157  int clientFd = mockService.BlockForOneClient();
158  if (-1 == clientFd)
159  {
160  BOOST_FAIL("Failed to connect client");
161  }
162 
163  // Give the profiling service sending thread time start executing and send the stream metadata.
164  while (profilingService.GetCurrentState() != profiling::ProfilingState::WaitingForAck)
165  {
166  if (timeSlept >= timeout)
167  {
168  BOOST_FAIL("Timeout: Profiling service did not switch to WaitingForAck state");
169  }
170  std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
171  timeSlept += sleepTime;
172  }
173 
174  profilingService.Update();
175  // Read the stream metadata on the mock side.
176  if (!mockService.WaitForStreamMetaData())
177  {
178  BOOST_FAIL("Failed to receive StreamMetaData");
179  }
180  // Send Ack from GatorD
181  mockService.SendConnectionAck();
182 
183  timeSlept = 0;
184  while (profilingService.GetCurrentState() != profiling::ProfilingState::Active)
185  {
186  if (timeSlept >= timeout)
187  {
188  BOOST_FAIL("Timeout: Profiling service did not switch to Active state");
189  }
190  std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
191  timeSlept += sleepTime;
192  }
193 
194  mockService.LaunchReceivingThread();
195  // As part of the default startup of the profiling service a counter directory packet will be sent.
196  timeSlept = 0;
197  while (!directoryCaptureCommandHandler.ParsedCounterDirectory())
198  {
199  if (timeSlept >= timeout)
200  {
201  BOOST_FAIL("Timeout: MockGatord did not receive counter directory packet");
202  }
203  std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
204  timeSlept += sleepTime;
205  }
206 
207  const profiling::ICounterDirectory& serviceCounterDirectory = profilingService.GetCounterDirectory();
208  const profiling::ICounterDirectory& receivedCounterDirectory = directoryCaptureCommandHandler.GetCounterDirectory();
209 
210  // Compare thre basics of the counter directory from the service and the one we received over the wire.
211  BOOST_ASSERT(serviceCounterDirectory.GetDeviceCount() == receivedCounterDirectory.GetDeviceCount());
212  BOOST_ASSERT(serviceCounterDirectory.GetCounterSetCount() == receivedCounterDirectory.GetCounterSetCount());
213  BOOST_ASSERT(serviceCounterDirectory.GetCategoryCount() == receivedCounterDirectory.GetCategoryCount());
214  BOOST_ASSERT(serviceCounterDirectory.GetCounterCount() == receivedCounterDirectory.GetCounterCount());
215 
216  receivedCounterDirectory.GetDeviceCount();
217  serviceCounterDirectory.GetDeviceCount();
218 
219  const profiling::Devices& serviceDevices = serviceCounterDirectory.GetDevices();
220  for (auto& device : serviceDevices)
221  {
222  // Find the same device in the received counter directory.
223  auto foundDevice = receivedCounterDirectory.GetDevices().find(device.second->m_Uid);
224  BOOST_CHECK(foundDevice != receivedCounterDirectory.GetDevices().end());
225  BOOST_CHECK(device.second->m_Name.compare((*foundDevice).second->m_Name) == 0);
226  BOOST_CHECK(device.second->m_Cores == (*foundDevice).second->m_Cores);
227  }
228 
229  const profiling::CounterSets& serviceCounterSets = serviceCounterDirectory.GetCounterSets();
230  for (auto& counterSet : serviceCounterSets)
231  {
232  // Find the same counter set in the received counter directory.
233  auto foundCounterSet = receivedCounterDirectory.GetCounterSets().find(counterSet.second->m_Uid);
234  BOOST_CHECK(foundCounterSet != receivedCounterDirectory.GetCounterSets().end());
235  BOOST_CHECK(counterSet.second->m_Name.compare((*foundCounterSet).second->m_Name) == 0);
236  BOOST_CHECK(counterSet.second->m_Count == (*foundCounterSet).second->m_Count);
237  }
238 
239  const profiling::Categories& serviceCategories = serviceCounterDirectory.GetCategories();
240  for (auto& category : serviceCategories)
241  {
242  for (auto& receivedCategory : receivedCounterDirectory.GetCategories())
243  {
244  if (receivedCategory->m_Name.compare(category->m_Name) == 0)
245  {
246  // We've found the matching category.
247  // Now look at the interiors of the counters. Start by sorting them.
248  std::sort(category->m_Counters.begin(), category->m_Counters.end());
249  std::sort(receivedCategory->m_Counters.begin(), receivedCategory->m_Counters.end());
250  // When comparing uid's here we need to translate them.
251  std::function<bool(const uint16_t&, const uint16_t&)> comparator =
252  [&directoryCaptureCommandHandler](const uint16_t& first, const uint16_t& second) {
253  uint16_t translated = directoryCaptureCommandHandler.TranslateUIDCopyToOriginal(second);
254  if (translated == first)
255  {
256  return true;
257  }
258  return false;
259  };
260  // Then let vector == do the work.
261  BOOST_CHECK(std::equal(category->m_Counters.begin(), category->m_Counters.end(),
262  receivedCategory->m_Counters.begin(), comparator));
263  break;
264  }
265  }
266  }
267 
268  // Finally check the content of the counters.
269  const profiling::Counters& receivedCounters = receivedCounterDirectory.GetCounters();
270  for (auto& receivedCounter : receivedCounters)
271  {
272  // Translate the Uid and find the corresponding counter in the original counter directory.
273  // Note we can't check m_MaxCounterUid here as it will likely differ between the two counter directories.
274  uint16_t translated = directoryCaptureCommandHandler.TranslateUIDCopyToOriginal(receivedCounter.first);
275  const profiling::Counter* serviceCounter = serviceCounterDirectory.GetCounter(translated);
276  BOOST_CHECK(serviceCounter->m_DeviceUid == receivedCounter.second->m_DeviceUid);
277  BOOST_CHECK(serviceCounter->m_Name.compare(receivedCounter.second->m_Name) == 0);
278  BOOST_CHECK(serviceCounter->m_CounterSetUid == receivedCounter.second->m_CounterSetUid);
279  BOOST_CHECK(serviceCounter->m_Multiplier == receivedCounter.second->m_Multiplier);
280  BOOST_CHECK(serviceCounter->m_Interpolation == receivedCounter.second->m_Interpolation);
281  BOOST_CHECK(serviceCounter->m_Class == receivedCounter.second->m_Class);
282  BOOST_CHECK(serviceCounter->m_Units.compare(receivedCounter.second->m_Units) == 0);
283  BOOST_CHECK(serviceCounter->m_Description.compare(receivedCounter.second->m_Description) == 0);
284  }
285 
286  mockService.WaitForReceivingThread();
287  options.m_EnableProfiling = false;
288  profilingService.ResetExternalProfilingOptions(options, true);
289 
290  // Future tests here will add counters to the ProfilingService, increment values and examine
291  // PeriodicCounterCapture data received. These are yet to be integrated.
292 }
293 
BOOST_AUTO_TEST_SUITE(TensorflowLiteParser)
static ProfilingService & Instance()
ProfilingState GetCurrentState() const
void WriteUint16(const IPacketBufferPtr &packetBuffer, unsigned int offset, uint16_t value)
void WriteUint32(const IPacketBufferPtr &packetBuffer, unsigned int offset, uint32_t value)
std::unordered_map< uint16_t, CounterPtr > Counters
Version ResolvePacketVersion(uint32_t familyId, uint32_t packetId) const
bool OpenListeningSocket(std::string udsNamespace)
Establish the Unix domain socket and set it to listen for connections.
virtual uint16_t GetCounterCount() const =0
Copyright (c) 2020 ARM Limited.
virtual const CounterSets & GetCounterSets() const =0
ProfilingService & profilingService
virtual uint16_t GetCategoryCount() const =0
BOOST_CHECK(profilingService.GetCurrentState()==ProfilingState::WaitingForAck)
std::unordered_map< uint16_t, CounterSetPtr > CounterSets
virtual const Categories & GetCategories() const =0
bool WaitForStreamMetaData()
Once the connection is open wait to receive the stream meta data packet from the client.
virtual const Devices & GetDevices() const =0
void RegisterFunctor(CommandHandlerFunctor *functor, uint32_t familyId, uint32_t packetId, uint32_t version)
void ResetExternalProfilingOptions(const ExternalProfilingOptions &options, bool resetProfilingService=false)
virtual uint16_t GetDeviceCount() const =0
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
Definition: NumericCast.hpp:33
BOOST_AUTO_TEST_CASE(CheckConvolution2dLayer)
bool LaunchReceivingThread()
Start the thread that will receive all packets and print them nicely to stdout.
virtual const Counter * GetCounter(uint16_t uid) const =0
void WriteUint64(const std::unique_ptr< IPacketBuffer > &packetBuffer, unsigned int offset, uint64_t value)
std::unordered_set< CategoryPtr > Categories
virtual uint16_t GetCounterSetCount() const =0
A class that implements a Mock Gatord server.
BOOST_AUTO_TEST_SUITE_END()
virtual const Counters & GetCounters() const =0
std::unordered_map< uint16_t, DevicePtr > Devices
void WaitForReceivingThread()
This is a placeholder method to prevent main exiting.
armnn::Runtime::CreationOptions::ExternalProfilingOptions options
const ICounterDirectory & GetCounterDirectory() const
armnnUtils::Sockets::Socket BlockForOneClient()
Block waiting to accept one client to connect to the UDS.
void SendConnectionAck()
Send a connection acknowledged packet back to the client.