ArmNN
 22.05.01
GatordMockTests.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
7 #include <GatordMockService.hpp>
8 #include <Runtime.hpp>
10 
11 #include <client/src/ProfilingService.hpp>
12 #include <client/src/TimelinePacketWriterFactory.hpp>
13 
15 
16 #include <common/include/LabelsAndEventClasses.hpp>
17 #include <common/include/CommandHandlerRegistry.hpp>
18 
19 #include <armnn/utility/Assert.hpp>
21 
22 #include <server/include/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp>
23 #include <server/include/timelineDecoder/TimelineDecoder.hpp>
24 #include <server/include/basePipeServer/ConnectionHandler.hpp>
25 
26 #include <doctest/doctest.h>
27 
28 TEST_SUITE("GatordMockTests")
29 {
30 using namespace armnn;
31 using namespace std::this_thread;
32 using namespace std::chrono_literals;
33 
34 TEST_CASE("CounterCaptureHandlingTest")
35 {
36  arm::pipe::PacketVersionResolver packetVersionResolver;
37 
38  // Data with timestamp, counter idx & counter values
39  std::vector<std::pair<uint16_t, uint32_t>> indexValuePairs;
40  indexValuePairs.reserve(5);
41  indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t>(0, 100));
42  indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t>(1, 200));
43  indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t>(2, 300));
44  indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t>(3, 400));
45  indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t>(4, 500));
46 
47  // ((uint16_t (2 bytes) + uint32_t (4 bytes)) * 5) + word1 + word2
48  uint32_t dataLength = 38;
49 
50  // Simulate two different packets incoming 500 ms apart
51  uint64_t time = static_cast<uint64_t>(
52  std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch())
53  .count());
54 
55  uint64_t time2 = time + 5000;
56 
57  // UniqueData required for Packet class
58  std::unique_ptr<unsigned char[]> uniqueData1 = std::make_unique<unsigned char[]>(dataLength);
59  unsigned char* data1 = reinterpret_cast<unsigned char*>(uniqueData1.get());
60 
61  std::unique_ptr<unsigned char[]> uniqueData2 = std::make_unique<unsigned char[]>(dataLength);
62  unsigned char* data2 = reinterpret_cast<unsigned char*>(uniqueData2.get());
63 
64  uint32_t sizeOfUint64 = armnn::numeric_cast<uint32_t>(sizeof(uint64_t));
65  uint32_t sizeOfUint32 = armnn::numeric_cast<uint32_t>(sizeof(uint32_t));
66  uint32_t sizeOfUint16 = armnn::numeric_cast<uint32_t>(sizeof(uint16_t));
67  // Offset index to point to mem address
68  uint32_t offset = 0;
69 
70  arm::pipe::WriteUint64(data1, offset, time);
71  offset += sizeOfUint64;
72  for (const auto& pair : indexValuePairs)
73  {
74  arm::pipe::WriteUint16(data1, offset, pair.first);
75  offset += sizeOfUint16;
76  arm::pipe::WriteUint32(data1, offset, pair.second);
77  offset += sizeOfUint32;
78  }
79 
80  offset = 0;
81 
82  arm::pipe::WriteUint64(data2, offset, time2);
83  offset += sizeOfUint64;
84  for (const auto& pair : indexValuePairs)
85  {
86  arm::pipe::WriteUint16(data2, offset, pair.first);
87  offset += sizeOfUint16;
88  arm::pipe::WriteUint32(data2, offset, pair.second);
89  offset += sizeOfUint32;
90  }
91 
92  uint32_t headerWord1 = packetVersionResolver.ResolvePacketVersion(0, 4).GetEncodedValue();
93  // Create packet to send through to the command functor
94  arm::pipe::Packet packet1(headerWord1, dataLength, uniqueData1);
95  arm::pipe::Packet packet2(headerWord1, dataLength, uniqueData2);
96 
97  gatordmock::PeriodicCounterCaptureCommandHandler commandHandler(0, 4, headerWord1, true);
98 
99  // Simulate two separate packets coming in to calculate period
100  commandHandler(packet1);
101  commandHandler(packet2);
102 
103  ARMNN_ASSERT(commandHandler.m_CurrentPeriodValue == 5000);
104 
105  for (size_t i = 0; i < commandHandler.m_CounterCaptureValues.m_Uids.size(); ++i)
106  {
107  ARMNN_ASSERT(commandHandler.m_CounterCaptureValues.m_Uids[i] == i);
108  }
109 }
110 
111 void WaitFor(std::function<bool()> predicate, std::string errorMsg, uint32_t timeout = 2000, uint32_t sleepTime = 50)
112 {
113  uint32_t timeSlept = 0;
114  while (!predicate())
115  {
116  if (timeSlept >= timeout)
117  {
118  FAIL("Timeout: " << errorMsg);
119  }
120  std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
121  timeSlept += sleepTime;
122  }
123 }
124 
125 void CheckTimelineDirectory(arm::pipe::TimelineDirectoryCaptureCommandHandler& commandHandler)
126 {
127  uint32_t uint8_t_size = sizeof(uint8_t);
128  uint32_t uint32_t_size = sizeof(uint32_t);
129  uint32_t uint64_t_size = sizeof(uint64_t);
130  uint32_t threadId_size = sizeof(int);
131 
132  arm::pipe::BufferManager bufferManager(5);
133  arm::pipe::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager);
134 
135  std::unique_ptr<arm::pipe::ISendTimelinePacket> sendTimelinePacket =
136  timelinePacketWriterFactory.GetSendTimelinePacket();
137 
138  sendTimelinePacket->SendTimelineMessageDirectoryPackage();
139  sendTimelinePacket->Commit();
140 
141  std::vector<arm::pipe::SwTraceMessage> swTraceBufferMessages;
142 
143  unsigned int offset = uint32_t_size * 2;
144 
145  std::unique_ptr<arm::pipe::IPacketBuffer> packetBuffer = bufferManager.GetReadableBuffer();
146 
147  uint8_t readStreamVersion = ReadUint8(packetBuffer, offset);
148  CHECK(readStreamVersion == 4);
149  offset += uint8_t_size;
150  uint8_t readPointerBytes = ReadUint8(packetBuffer, offset);
151  CHECK(readPointerBytes == uint64_t_size);
152  offset += uint8_t_size;
153  uint8_t readThreadIdBytes = ReadUint8(packetBuffer, offset);
154  CHECK(readThreadIdBytes == threadId_size);
155  offset += uint8_t_size;
156 
157  uint32_t declarationSize = arm::pipe::ReadUint32(packetBuffer, offset);
158  offset += uint32_t_size;
159  for(uint32_t i = 0; i < declarationSize; ++i)
160  {
161  swTraceBufferMessages.push_back(arm::pipe::ReadSwTraceMessage(packetBuffer->GetReadableData(),
162  offset,
163  packetBuffer->GetSize()));
164  }
165 
166  for(uint32_t index = 0; index < declarationSize; ++index)
167  {
168  arm::pipe::SwTraceMessage& bufferMessage = swTraceBufferMessages[index];
169  arm::pipe::SwTraceMessage& handlerMessage = commandHandler.m_SwTraceMessages[index];
170 
171  CHECK(bufferMessage.m_Name == handlerMessage.m_Name);
172  CHECK(bufferMessage.m_UiName == handlerMessage.m_UiName);
173  CHECK(bufferMessage.m_Id == handlerMessage.m_Id);
174 
175  CHECK(bufferMessage.m_ArgTypes.size() == handlerMessage.m_ArgTypes.size());
176  for(uint32_t i = 0; i < bufferMessage.m_ArgTypes.size(); ++i)
177  {
178  CHECK(bufferMessage.m_ArgTypes[i] == handlerMessage.m_ArgTypes[i]);
179  }
180 
181  CHECK(bufferMessage.m_ArgNames.size() == handlerMessage.m_ArgNames.size());
182  for(uint32_t i = 0; i < bufferMessage.m_ArgNames.size(); ++i)
183  {
184  CHECK(bufferMessage.m_ArgNames[i] == handlerMessage.m_ArgNames[i]);
185  }
186  }
187 }
188 
189 void CheckTimelinePackets(arm::pipe::TimelineDecoder& timelineDecoder)
190 {
191  unsigned int i = 0; // Use a postfix increment to avoid changing indexes each time the packet gets updated.
192  timelineDecoder.ApplyToModel([&](arm::pipe::TimelineDecoder::Model& m) {
193  CHECK(m.m_Labels[i].m_Guid == arm::pipe::LabelsAndEventClasses::NAME_GUID);
194  CHECK(m.m_Labels[i++].m_Name == arm::pipe::LabelsAndEventClasses::NAME_LABEL);
195 
196  CHECK(m.m_Labels[i].m_Guid == arm::pipe::LabelsAndEventClasses::TYPE_GUID);
197  CHECK(m.m_Labels[i++].m_Name == arm::pipe::LabelsAndEventClasses::TYPE_LABEL);
198 
199  CHECK(m.m_Labels[i].m_Guid == arm::pipe::LabelsAndEventClasses::INDEX_GUID);
200  CHECK(m.m_Labels[i++].m_Name == arm::pipe::LabelsAndEventClasses::INDEX_LABEL);
201 
202  CHECK(m.m_Labels[i].m_Guid == arm::pipe::LabelsAndEventClasses::BACKENDID_GUID);
203  CHECK(m.m_Labels[i++].m_Name == arm::pipe::LabelsAndEventClasses::BACKENDID_LABEL);
204 
205  CHECK(m.m_Labels[i].m_Guid == arm::pipe::LabelsAndEventClasses::CHILD_GUID);
206  CHECK(m.m_Labels[i++].m_Name == arm::pipe::LabelsAndEventClasses::CHILD_LABEL);
207 
208  CHECK(m.m_Labels[i].m_Guid == arm::pipe::LabelsAndEventClasses::EXECUTION_OF_GUID);
209  CHECK(m.m_Labels[i++].m_Name ==
210  arm::pipe::LabelsAndEventClasses::EXECUTION_OF_LABEL);
211 
212  CHECK(m.m_Labels[i].m_Guid == arm::pipe::LabelsAndEventClasses::PROCESS_ID_GUID);
213  CHECK(m.m_Labels[i++].m_Name ==
214  arm::pipe::LabelsAndEventClasses::PROCESS_ID_LABEL);
215 
216  CHECK(m.m_Labels[i].m_Guid == arm::pipe::LabelsAndEventClasses::LAYER_GUID);
217  CHECK(m.m_Labels[i++].m_Name == arm::pipe::LabelsAndEventClasses::LAYER);
218 
219  CHECK(m.m_Labels[i].m_Guid == arm::pipe::LabelsAndEventClasses::WORKLOAD_GUID);
220  CHECK(m.m_Labels[i++].m_Name == arm::pipe::LabelsAndEventClasses::WORKLOAD);
221 
222  CHECK(m.m_Labels[i].m_Guid == arm::pipe::LabelsAndEventClasses::NETWORK_GUID);
223  CHECK(m.m_Labels[i++].m_Name == arm::pipe::LabelsAndEventClasses::NETWORK);
224 
225  CHECK(m.m_Labels[i].m_Guid == arm::pipe::LabelsAndEventClasses::CONNECTION_GUID);
226  CHECK(m.m_Labels[i++].m_Name == arm::pipe::LabelsAndEventClasses::CONNECTION);
227 
228  CHECK(m.m_Labels[i].m_Guid == arm::pipe::LabelsAndEventClasses::INFERENCE_GUID);
229  CHECK(m.m_Labels[i++].m_Name == arm::pipe::LabelsAndEventClasses::INFERENCE);
230 
231  CHECK(m.m_Labels[i].m_Guid ==
232  arm::pipe::LabelsAndEventClasses::WORKLOAD_EXECUTION_GUID);
233  CHECK(m.m_Labels[i++].m_Name ==
234  arm::pipe::LabelsAndEventClasses::WORKLOAD_EXECUTION);
235 
236  CHECK(m.m_EventClasses[0].m_Guid ==
237  arm::pipe::LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS);
238  CHECK(m.m_EventClasses[1].m_Guid ==
239  arm::pipe::LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS);
240  });
241 }
242 
243 TEST_CASE("GatorDMockEndToEnd")
244 {
245  // The purpose of this test is to setup both sides of the profiling service and get to the point of receiving
246  // performance data.
247 
248  // Setup the mock service to bind to the UDS.
249  std::string udsNamespace = "gatord_namespace";
250 
251  CHECK_NOTHROW(arm::pipe::ConnectionHandler connectionHandler(udsNamespace, false));
252 
253  arm::pipe::ConnectionHandler connectionHandler(udsNamespace, false);
254 
255  // Enable the profiling service.
256  arm::pipe::ProfilingOptions options;
257  options.m_EnableProfiling = true;
258  options.m_TimelineEnabled = true;
259 
261  arm::pipe::ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER,
262  initialiser,
263  arm::pipe::ARMNN_SOFTWARE_INFO,
264  arm::pipe::ARMNN_SOFTWARE_VERSION,
265  arm::pipe::ARMNN_HARDWARE_VERSION);
266  profilingService.ResetExternalProfilingOptions(options, true);
267 
268  // Bring the profiling service to the "WaitingForAck" state
269  CHECK(profilingService.GetCurrentState() == arm::pipe::ProfilingState::Uninitialised);
270  profilingService.Update();
271  CHECK(profilingService.GetCurrentState() == arm::pipe::ProfilingState::NotConnected);
272  profilingService.Update();
273 
274  // Connect the profiling service
275  auto basePipeServer = connectionHandler.GetNewBasePipeServer(false);
276 
277  // Connect the profiling service to the mock Gatord.
278  gatordmock::GatordMockService mockService(std::move(basePipeServer), false);
279 
280  arm::pipe::TimelineDecoder& timelineDecoder = mockService.GetTimelineDecoder();
281  arm::pipe::DirectoryCaptureCommandHandler& directoryCaptureCommandHandler =
282  mockService.GetDirectoryCaptureCommandHandler();
283 
284  // Give the profiling service sending thread time start executing and send the stream metadata.
285  WaitFor([&](){return profilingService.GetCurrentState() == arm::pipe::ProfilingState::WaitingForAck;},
286  "Profiling service did not switch to WaitingForAck state");
287 
288  profilingService.Update();
289  // Read the stream metadata on the mock side.
290  if (!mockService.WaitForStreamMetaData())
291  {
292  FAIL("Failed to receive StreamMetaData");
293  }
294  // Send Ack from GatorD
295  mockService.SendConnectionAck();
296  // And start to listen for packets
297  mockService.LaunchReceivingThread();
298 
299  WaitFor([&](){return profilingService.GetCurrentState() == arm::pipe::ProfilingState::Active;},
300  "Profiling service did not switch to Active state");
301 
302  // As part of the default startup of the profiling service a counter directory packet will be sent.
303  WaitFor([&](){return directoryCaptureCommandHandler.ParsedCounterDirectory();},
304  "MockGatord did not receive counter directory packet");
305 
306  // Following that we will receive a collection of well known timeline labels and event classes
307  WaitFor([&](){return timelineDecoder.ApplyToModel([&](arm::pipe::TimelineDecoder::Model& m){
308  return m.m_EventClasses.size() >= 2;});},
309  "MockGatord did not receive well known timeline labels and event classes");
310 
311  CheckTimelineDirectory(mockService.GetTimelineDirectoryCaptureCommandHandler());
312  // Verify the commonly used timeline packets sent when the profiling service enters the active state
313  CheckTimelinePackets(timelineDecoder);
314 
315  const arm::pipe::ICounterDirectory& serviceCounterDirectory = profilingService.GetCounterDirectory();
316  const arm::pipe::ICounterDirectory& receivedCounterDirectory = directoryCaptureCommandHandler.GetCounterDirectory();
317 
318  // Compare the basics of the counter directory from the service and the one we received over the wire.
319  CHECK(serviceCounterDirectory.GetDeviceCount() == receivedCounterDirectory.GetDeviceCount());
320  CHECK(serviceCounterDirectory.GetCounterSetCount() == receivedCounterDirectory.GetCounterSetCount());
321  CHECK(serviceCounterDirectory.GetCategoryCount() == receivedCounterDirectory.GetCategoryCount());
322  CHECK(serviceCounterDirectory.GetCounterCount() == receivedCounterDirectory.GetCounterCount());
323 
324  receivedCounterDirectory.GetDeviceCount();
325  serviceCounterDirectory.GetDeviceCount();
326 
327  const arm::pipe::Devices& serviceDevices = serviceCounterDirectory.GetDevices();
328  for (auto& device : serviceDevices)
329  {
330  // Find the same device in the received counter directory.
331  auto foundDevice = receivedCounterDirectory.GetDevices().find(device.second->m_Uid);
332  CHECK(foundDevice != receivedCounterDirectory.GetDevices().end());
333  CHECK(device.second->m_Name.compare((*foundDevice).second->m_Name) == 0);
334  CHECK(device.second->m_Cores == (*foundDevice).second->m_Cores);
335  }
336 
337  const arm::pipe::CounterSets& serviceCounterSets = serviceCounterDirectory.GetCounterSets();
338  for (auto& counterSet : serviceCounterSets)
339  {
340  // Find the same counter set in the received counter directory.
341  auto foundCounterSet = receivedCounterDirectory.GetCounterSets().find(counterSet.second->m_Uid);
342  CHECK(foundCounterSet != receivedCounterDirectory.GetCounterSets().end());
343  CHECK(counterSet.second->m_Name.compare((*foundCounterSet).second->m_Name) == 0);
344  CHECK(counterSet.second->m_Count == (*foundCounterSet).second->m_Count);
345  }
346 
347  const arm::pipe::Categories& serviceCategories = serviceCounterDirectory.GetCategories();
348  for (auto& category : serviceCategories)
349  {
350  for (auto& receivedCategory : receivedCounterDirectory.GetCategories())
351  {
352  if (receivedCategory->m_Name.compare(category->m_Name) == 0)
353  {
354  // We've found the matching category.
355  // Now look at the interiors of the counters. Start by sorting them.
356  std::sort(category->m_Counters.begin(), category->m_Counters.end());
357  std::sort(receivedCategory->m_Counters.begin(), receivedCategory->m_Counters.end());
358  // When comparing uid's here we need to translate them.
359  std::function<bool(const uint16_t&, const uint16_t&)> comparator =
360  [&directoryCaptureCommandHandler](const uint16_t& first, const uint16_t& second) {
361  uint16_t translated = directoryCaptureCommandHandler.TranslateUIDCopyToOriginal(second);
362  if (translated == first)
363  {
364  return true;
365  }
366  return false;
367  };
368  // Then let vector == do the work.
369  CHECK(std::equal(category->m_Counters.begin(), category->m_Counters.end(),
370  receivedCategory->m_Counters.begin(), comparator));
371  break;
372  }
373  }
374  }
375 
376  // Finally check the content of the counters.
377  const arm::pipe::Counters& receivedCounters = receivedCounterDirectory.GetCounters();
378  for (auto& receivedCounter : receivedCounters)
379  {
380  // Translate the Uid and find the corresponding counter in the original counter directory.
381  // Note we can't check m_MaxCounterUid here as it will likely differ between the two counter directories.
382  uint16_t translated = directoryCaptureCommandHandler.TranslateUIDCopyToOriginal(receivedCounter.first);
383  const arm::pipe::Counter* serviceCounter = serviceCounterDirectory.GetCounter(translated);
384  CHECK(serviceCounter->m_DeviceUid == receivedCounter.second->m_DeviceUid);
385  CHECK(serviceCounter->m_Name.compare(receivedCounter.second->m_Name) == 0);
386  CHECK(serviceCounter->m_CounterSetUid == receivedCounter.second->m_CounterSetUid);
387  CHECK(serviceCounter->m_Multiplier == receivedCounter.second->m_Multiplier);
388  CHECK(serviceCounter->m_Interpolation == receivedCounter.second->m_Interpolation);
389  CHECK(serviceCounter->m_Class == receivedCounter.second->m_Class);
390  CHECK(serviceCounter->m_Units.compare(receivedCounter.second->m_Units) == 0);
391  CHECK(serviceCounter->m_Description.compare(receivedCounter.second->m_Description) == 0);
392  }
393 
394  mockService.WaitForReceivingThread();
395  options.m_EnableProfiling = false;
396  profilingService.ResetExternalProfilingOptions(options, true);
397  // Future tests here will add counters to the ProfilingService, increment values and examine
398  // PeriodicCounterCapture data received. These are yet to be integrated.
399 }
400 
401 TEST_CASE("GatorDMockTimeLineActivation")
402 {
403  // This test requires the CpuRef backend to be enabled
404  if(!BackendRegistryInstance().IsBackendRegistered("CpuRef"))
405  {
406  return;
407  }
408  armnn::MockBackendInitialiser initialiser;
409  // Setup the mock service to bind to the UDS.
410  std::string udsNamespace = "gatord_namespace";
411 
412  arm::pipe::ConnectionHandler connectionHandler(udsNamespace, false);
413 
415  options.m_ProfilingOptions.m_EnableProfiling = true;
416  options.m_ProfilingOptions.m_TimelineEnabled = true;
417  armnn::RuntimeImpl runtime(options);
418 
419  auto basePipeServer = connectionHandler.GetNewBasePipeServer(false);
420  gatordmock::GatordMockService mockService(std::move(basePipeServer), false);
421 
422  // Read the stream metadata on the mock side.
423  if (!mockService.WaitForStreamMetaData())
424  {
425  FAIL("Failed to receive StreamMetaData");
426  }
427 
429  armnn::MockBackendProfilingContext* mockBackEndProfilingContext = mockProfilingService.GetContext();
430 
431  // Send Ack from GatorD
432  mockService.SendConnectionAck();
433  // And start to listen for packets
434  mockService.LaunchReceivingThread();
435 
436  // Build and optimize a simple network while we wait
438 
439  IConnectableLayer* input = net->AddInputLayer(0, "input");
440 
441  NormalizationDescriptor descriptor;
442  IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor, "normalization");
443 
444  IConnectableLayer* output = net->AddOutputLayer(0, "output");
445 
446  input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
447  normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
448 
449  input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
450  normalize->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
451 
452  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
453  IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime.GetDeviceSpec());
454 
455  WaitFor([&](){return mockService.GetDirectoryCaptureCommandHandler().ParsedCounterDirectory();},
456  "MockGatord did not receive counter directory packet");
457 
458  arm::pipe::TimelineDecoder& timelineDecoder = mockService.GetTimelineDecoder();
459 
460  WaitFor([&](){return timelineDecoder.ApplyToModel([&](arm::pipe::TimelineDecoder::Model& m){
461  return m.m_EventClasses.size() >= 2;});},
462  "MockGatord did not receive well known timeline labels");
463 
464  WaitFor([&](){return timelineDecoder.ApplyToModel([&](arm::pipe::TimelineDecoder::Model& m){
465  return m.m_Entities.size() >= 1;});},
466  "MockGatord did not receive mock backend test entity");
467 
468  // Packets we expect from SendWellKnownLabelsAndEventClassesTest
469  timelineDecoder.ApplyToModel([&](const arm::pipe::TimelineDecoder::Model& m){
470  CHECK(m.m_Entities.size() == 1);
471  CHECK(m.m_EventClasses.size() == 2);
472  CHECK(m.m_Labels.size() == 15);
473  CHECK(m.m_Relationships.size() == 0);
474  CHECK(m.m_Events.size() == 0);
475  });
476 
477  mockService.SendDeactivateTimelinePacket();
478 
479  WaitFor([&](){return !mockBackEndProfilingContext->TimelineReportingEnabled();},
480  "Timeline packets were not deactivated");
481 
482  // Load the network into runtime now that timeline reporting is disabled
483  armnn::NetworkId netId;
484  runtime.LoadNetwork(netId, std::move(optNet));
485 
486  // Now activate timeline packets
487  mockService.SendActivateTimelinePacket();
488 
489  WaitFor([&](){return mockBackEndProfilingContext->TimelineReportingEnabled();},
490  "Timeline packets were not activated");
491 
492  // Once TimelineReporting is Enabled additional activateTimelinePackets should be ignored
493  mockService.SendActivateTimelinePacket();
494  mockService.SendActivateTimelinePacket();
495 
496  // Once timeline packets have been reactivated the ActivateTimelineReportingCommandHandler will resend the
497  // SendWellKnownLabelsAndEventClasses and then send the structure of any loaded networks
498  WaitFor([&](){return timelineDecoder.ApplyToModel([&](arm::pipe::TimelineDecoder::Model& m){
499  return m.m_Labels.size() >= 24;});},
500  "MockGatord did not receive well known timeline labels");
501 
502  // Packets we expect from SendWellKnownLabelsAndEventClassesTest * 2 + network above (input, norm, backend, output)
503  timelineDecoder.ApplyToModel([&](const arm::pipe::TimelineDecoder::Model& m){
504  CHECK(m.m_Entities.size() == 6);
505  CHECK(m.m_EventClasses.size() == 4);
506  CHECK(m.m_Labels.size() == 34);
507  CHECK(m.m_Relationships.size() == 15);
508  CHECK(m.m_Events.size() == 0);
509  });
510 
511  mockService.WaitForReceivingThread();
512  GetProfilingService(&runtime).Disconnect();
513 }
514 
515 }
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:66
CPU Execution: Reference C++ kernels.
arm::pipe::TimelineDirectoryCaptureCommandHandler & GetTimelineDirectoryCaptureCommandHandler()
BackendRegistry & BackendRegistryInstance()
Status LoadNetwork(NetworkId &networkIdOut, IOptimizedNetworkPtr network)
Loads a complete network into the Runtime.
Definition: Runtime.cpp:163
Copyright (c) 2021 ARM Limited and Contributors.
void SendDeactivateTimelinePacket()
Send a deactivate timeline packet back to the client.
bool m_EnableProfiling
Indicates whether external profiling is enabled or not.
Definition: IRuntime.hpp:138
void SendActivateTimelinePacket()
Send a activate timeline packet back to the client.
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
bool WaitForStreamMetaData()
Once the connection is open wait to receive the stream meta data packet from the client.
arm::pipe::DirectoryCaptureCommandHandler & GetDirectoryCaptureCommandHandler()
arm::pipe::TimelineDecoder & GetTimelineDecoder()
IOptimizedNetworkPtr Optimize(const INetwork &network, const std::vector< BackendId > &backendPreferences, const IDeviceSpec &deviceSpec, const OptimizerOptions &options=OptimizerOptions(), Optional< std::vector< std::string > &> messages=EmptyOptional())
Create an optimized version of the network.
Definition: Network.cpp:1847
const IDeviceSpec & GetDeviceSpec() const
Definition: Runtime.hpp:90
TEST_SUITE("GatordMockTests")
int NetworkId
Definition: IRuntime.hpp:27
std::unique_ptr< IOptimizedNetwork, void(*)(IOptimizedNetwork *network)> IOptimizedNetworkPtr
Definition: INetwork.hpp:242
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
bool LaunchReceivingThread()
Start the thread that will receive all packets and print them nicely to stdout.
static MockBackendProfilingService & Instance()
A class that implements a Mock Gatord server.
MockBackendProfilingContext * GetContext()
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
Definition: NumericCast.hpp:35
bool m_TimelineEnabled
Indicates whether external timeline profiling is enabled or not.
Definition: IRuntime.hpp:140
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
void WaitForReceivingThread()
This is a placeholder method to prevent main exiting.
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:241
virtual int Connect(IInputSlot &destination)=0
A NormalizationDescriptor for the NormalizationLayer.
ExternalProfilingOptions m_ProfilingOptions
Definition: IRuntime.hpp:153
arm::pipe::IProfilingService & GetProfilingService(armnn::RuntimeImpl *runtime)
Definition: TestUtils.cpp:59
static INetworkPtr Create(NetworkOptions networkOptions={})
Definition: Network.cpp:476
void SendConnectionAck()
Send a connection acknowledged packet back to the client.