xref: /aosp_15_r20/external/armnn/src/backends/backendsCommon/test/BackendProfilingTests.cpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1 //
2 // Copyright © 2020, 2023 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "ArmNNProfilingServiceInitialiser.hpp"
7 #include "MockBackendId.hpp"
8 #include "ProfilingOptionsConverter.hpp"
9 
10 #include <TestUtils.hpp>
11 
12 #include <armnn/BackendId.hpp>
13 #include <armnn/Logging.hpp>
14 
15 #include <armnn/profiling/ArmNNProfiling.hpp>
16 
17 #include <armnn/utility/IgnoreUnused.hpp>
18 
19 #include <armnnTestUtils/MockBackend.hpp>
20 
21 #include <client/include/CounterIdMap.hpp>
22 #include <client/include/Holder.hpp>
23 #include <client/include/ISendTimelinePacket.hpp>
24 #include <client/include/ProfilingOptions.hpp>
25 
26 #include <client/src/PeriodicCounterCapture.hpp>
27 #include <client/src/PeriodicCounterSelectionCommandHandler.hpp>
28 #include <client/src/ProfilingStateMachine.hpp>
29 #include <client/src/ProfilingUtils.hpp>
30 #include <client/src/RequestCounterDirectoryCommandHandler.hpp>
31 
32 #include <client/src/backends/BackendProfiling.hpp>
33 
34 #include <common/include/CounterDirectory.hpp>
35 #include <common/include/PacketVersionResolver.hpp>
36 
37 #include <doctest/doctest.h>
38 
39 #include <vector>
40 #include <cstdint>
41 #include <limits>
42 
43 namespace arm
44 {
45 
46 namespace pipe
47 {
48 
49 struct LogLevelSwapper
50 {
51 public:
LogLevelSwapperarm::pipe::LogLevelSwapper52     LogLevelSwapper(arm::pipe::LogSeverity severity)
53     {
54         // Set the new log level
55         arm::pipe::ConfigureLogging(true, true, severity);
56     }
~LogLevelSwapperarm::pipe::LogLevelSwapper57     ~LogLevelSwapper()
58     {
59         // The default log level for unit tests is "Fatal"
60         arm::pipe::ConfigureLogging(true, true, arm::pipe::LogSeverity::Fatal);
61     }
62 };
63 
64 } // namespace pipe
65 
66 } // namespace arm
67 
68 using namespace arm::pipe;
69 
70 class ReadCounterVals : public IReadCounterValues
71 {
IsCounterRegistered(uint16_t counterUid) const72     virtual bool IsCounterRegistered(uint16_t counterUid) const override
73     {
74         return (counterUid > 4 && counterUid < 11);
75     }
IsCounterRegistered(const std::string & counterName) const76     virtual bool IsCounterRegistered(const std::string& counterName) const override
77     {
78         armnn::IgnoreUnused(counterName);
79         return false;
80     }
GetCounterCount() const81     virtual uint16_t GetCounterCount() const override
82     {
83         return 1;
84     }
GetAbsoluteCounterValue(uint16_t counterUid) const85     virtual uint32_t GetAbsoluteCounterValue(uint16_t counterUid) const override
86     {
87         return counterUid;
88     }
GetDeltaCounterValue(uint16_t counterUid)89     virtual uint32_t GetDeltaCounterValue(uint16_t counterUid) override
90     {
91         return counterUid;
92     }
93 };
94 
95 class MockBackendSendCounterPacket : public ISendCounterPacket
96 {
97 public:
98     using IndexValuePairsVector = std::vector<CounterValue>;
99 
100     /// Create and write a StreamMetaDataPacket in the buffer
SendStreamMetaDataPacket()101     virtual void SendStreamMetaDataPacket() {}
102 
103     /// Create and write a CounterDirectoryPacket from the parameters to the buffer.
SendCounterDirectoryPacket(const ICounterDirectory & counterDirectory)104     virtual void SendCounterDirectoryPacket(const ICounterDirectory& counterDirectory)
105     {
106         armnn::IgnoreUnused(counterDirectory);
107     }
108 
109     /// Create and write a PeriodicCounterCapturePacket from the parameters to the buffer.
SendPeriodicCounterCapturePacket(uint64_t timestamp,const IndexValuePairsVector & values)110     virtual void SendPeriodicCounterCapturePacket(uint64_t timestamp, const IndexValuePairsVector& values)
111     {
112         m_timestamps.emplace_back(Timestamp{timestamp, values});
113     }
114 
115     /// Create and write a PeriodicCounterSelectionPacket from the parameters to the buffer.
SendPeriodicCounterSelectionPacket(uint32_t capturePeriod,const std::vector<uint16_t> & selectedCounterIds)116     virtual void SendPeriodicCounterSelectionPacket(uint32_t capturePeriod,
117                                                     const std::vector<uint16_t>& selectedCounterIds)
118     {
119         armnn::IgnoreUnused(capturePeriod);
120         armnn::IgnoreUnused(selectedCounterIds);
121     }
122 
GetTimestamps()123     std::vector<Timestamp> GetTimestamps()
124     {
125         return  m_timestamps;
126     }
127 
ClearTimestamps()128     void ClearTimestamps()
129     {
130         m_timestamps.clear();
131     }
132 
133 private:
134     std::vector<Timestamp> m_timestamps;
135 };
136 
PacketWriter(uint32_t period,std::vector<uint16_t> countervalues)137 arm::pipe::Packet PacketWriter(uint32_t period, std::vector<uint16_t> countervalues)
138 {
139     const uint32_t packetId = 0x40000;
140     uint32_t offset = 0;
141     uint32_t dataLength = static_cast<uint32_t>(4 + countervalues.size() * 2);
142     std::unique_ptr<unsigned char[]> uniqueData = std::make_unique<unsigned char[]>(dataLength);
143     unsigned char* data1                        = reinterpret_cast<unsigned char*>(uniqueData.get());
144 
145     WriteUint32(data1, offset, period);
146     offset += 4;
147     for (auto countervalue : countervalues)
148     {
149         WriteUint16(data1, offset, countervalue);
150         offset += 2;
151     }
152 
153     return {packetId, dataLength, uniqueData};
154 }
155 
156 TEST_SUITE("BackendProfilingTestSuite")
157 {
158 TEST_CASE("BackendProfilingCounterRegisterMockBackendTest")
159 {
160     arm::pipe::LogLevelSwapper logLevelSwapper(arm::pipe::LogSeverity::Fatal);
161 
162     // Reset the profiling service to the uninitialized state
163     armnn::IRuntime::CreationOptions options;
164     options.m_ProfilingOptions.m_EnableProfiling = true;
165 
166     armnn::MockBackendInitialiser initialiser;
167     // Create a runtime
168     armnn::RuntimeImpl runtime(options);
169 
170     unsigned int shiftedId = 0;
171 
172     // Check if the MockBackends 3 dummy counters {0, 1, 2-5 (four cores)} are registered
173     armnn::BackendId mockId = armnn::MockBackendId();
174     const ICounterMappings& counterMap = GetProfilingService(&runtime).GetCounterMappings();
175     CHECK(counterMap.GetGlobalId(0, mockId) == 5 + shiftedId);
176     CHECK(counterMap.GetGlobalId(1, mockId) == 6 + shiftedId);
177     CHECK(counterMap.GetGlobalId(2, mockId) == 7 + shiftedId);
178     CHECK(counterMap.GetGlobalId(3, mockId) == 8 + shiftedId);
179     CHECK(counterMap.GetGlobalId(4, mockId) == 9 + shiftedId);
180     CHECK(counterMap.GetGlobalId(5, mockId) == 10 + shiftedId);
181     options.m_ProfilingOptions.m_EnableProfiling = false;
182     GetProfilingService(&runtime).ResetExternalProfilingOptions(
183         ConvertExternalProfilingOptions(options.m_ProfilingOptions), true);
184 }
185 
186 TEST_CASE("TestBackendCounters")
187 {
188     arm::pipe::LogLevelSwapper logLevelSwapper(arm::pipe::LogSeverity::Fatal);
189 
190     Holder holder;
191     arm::pipe::PacketVersionResolver packetVersionResolver;
192     ProfilingStateMachine stateMachine;
193     ReadCounterVals readCounterVals;
194     CounterIdMap counterIdMap;
195     MockBackendSendCounterPacket sendCounterPacket;
196 
197     const std::string cpuAccId(GetComputeDeviceAsCString(armnn::Compute::CpuAcc));
198     const std::string gpuAccId(GetComputeDeviceAsCString(armnn::Compute::GpuAcc));
199 
200     ProfilingOptions options;
201     options.m_EnableProfiling = true;
202 
203     armnn::ArmNNProfilingServiceInitialiser initialiser;
204     std::unique_ptr<IProfilingService> profilingService = arm::pipe::IProfilingService::CreateProfilingService(
205         arm::pipe::MAX_ARMNN_COUNTER,
206         initialiser,
207         arm::pipe::ARMNN_SOFTWARE_INFO,
208         arm::pipe::ARMNN_SOFTWARE_VERSION,
209         arm::pipe::ARMNN_HARDWARE_VERSION);
210 
211     std::unique_ptr<IBackendProfiling> cpuBackendProfilingPtr =
212         std::make_unique<BackendProfiling>(options, *profilingService.get(), cpuAccId);
213     std::unique_ptr<IBackendProfiling> gpuBackendProfilingPtr =
214         std::make_unique<BackendProfiling>(options, *profilingService.get(), gpuAccId);
215 
216     std::shared_ptr<IBackendProfilingContext> cpuProfilingContextPtr =
217             std::make_shared<armnn::MockBackendProfilingContext>(cpuBackendProfilingPtr);
218     std::shared_ptr<IBackendProfilingContext> gpuProfilingContextPtr =
219             std::make_shared<armnn::MockBackendProfilingContext>(gpuBackendProfilingPtr);
220 
221     std::unordered_map<std::string,
222             std::shared_ptr<IBackendProfilingContext>> backendProfilingContexts;
223 
224     backendProfilingContexts[cpuAccId] = cpuProfilingContextPtr;
225     backendProfilingContexts[gpuAccId] = gpuProfilingContextPtr;
226 
227     uint16_t globalId = 5;
228 
229     counterIdMap.RegisterMapping(globalId++, 0, cpuAccId);
230     counterIdMap.RegisterMapping(globalId++, 1, cpuAccId);
231     counterIdMap.RegisterMapping(globalId++, 2, cpuAccId);
232 
233     counterIdMap.RegisterMapping(globalId++, 0, gpuAccId);
234     counterIdMap.RegisterMapping(globalId++, 1, gpuAccId);
235     counterIdMap.RegisterMapping(globalId++, 2, gpuAccId);
236 
237     backendProfilingContexts[cpuAccId] = cpuProfilingContextPtr;
238     backendProfilingContexts[gpuAccId] = gpuProfilingContextPtr;
239 
240     PeriodicCounterCapture periodicCounterCapture(holder, sendCounterPacket, readCounterVals,
241                                                   counterIdMap, backendProfilingContexts);
242 
243     uint16_t maxArmnnCounterId = 4;
244 
245     PeriodicCounterSelectionCommandHandler periodicCounterSelectionCommandHandler(0,
246                                                   4,
247                                                   packetVersionResolver.ResolvePacketVersion(0, 4).GetEncodedValue(),
248                                                   backendProfilingContexts,
249                                                   counterIdMap,
250                                                   holder,
251                                                   maxArmnnCounterId,
252                                                   periodicCounterCapture,
253                                                   readCounterVals,
254                                                   sendCounterPacket,
255                                                   stateMachine);
256 
257     stateMachine.TransitionToState(ProfilingState::NotConnected);
258     stateMachine.TransitionToState(ProfilingState::WaitingForAck);
259     stateMachine.TransitionToState(ProfilingState::Active);
260 
261     uint32_t period = 12345u;
262 
263     std::vector<uint16_t> cpuCounters{5, 6, 7};
264     std::vector<uint16_t> gpuCounters{8, 9, 10};
265 
266     // Request only gpu counters
267     periodicCounterSelectionCommandHandler(PacketWriter(period, gpuCounters));
268     periodicCounterCapture.Stop();
269 
270     std::set<std::string> activeIds = holder.GetCaptureData().GetActiveBackends();
271     CHECK(activeIds.size() == 1);
272     CHECK((activeIds.find(gpuAccId) != activeIds.end()));
273 
274     std::vector<Timestamp> recievedTimestamp = sendCounterPacket.GetTimestamps();
275 
276     CHECK(recievedTimestamp[0].timestamp == period);
277     CHECK(recievedTimestamp.size() == 1);
278     CHECK(recievedTimestamp[0].counterValues.size() == gpuCounters.size());
279     for (unsigned long i=0; i< gpuCounters.size(); ++i)
280     {
281         CHECK(recievedTimestamp[0].counterValues[i].counterId == gpuCounters[i]);
282         CHECK(recievedTimestamp[0].counterValues[i].counterValue == i + 1u);
283     }
284     sendCounterPacket.ClearTimestamps();
285 
286     // Request only cpu counters
287     periodicCounterSelectionCommandHandler(PacketWriter(period, cpuCounters));
288     periodicCounterCapture.Stop();
289 
290     activeIds = holder.GetCaptureData().GetActiveBackends();
291     CHECK(activeIds.size() == 1);
292     CHECK((activeIds.find(cpuAccId) != activeIds.end()));
293 
294     recievedTimestamp = sendCounterPacket.GetTimestamps();
295 
296     CHECK(recievedTimestamp[0].timestamp == period);
297     CHECK(recievedTimestamp.size() == 1);
298     CHECK(recievedTimestamp[0].counterValues.size() == cpuCounters.size());
299     for (unsigned long i=0; i< cpuCounters.size(); ++i)
300     {
301         CHECK(recievedTimestamp[0].counterValues[i].counterId == cpuCounters[i]);
302         CHECK(recievedTimestamp[0].counterValues[i].counterValue == i + 1u);
303     }
304     sendCounterPacket.ClearTimestamps();
305 
306     // Request combination of cpu & gpu counters with new period
307     period = 12222u;
308     periodicCounterSelectionCommandHandler(PacketWriter(period, {cpuCounters[0], gpuCounters[2],
309                                                                  gpuCounters[1], cpuCounters[1], gpuCounters[0]}));
310     periodicCounterCapture.Stop();
311 
312     activeIds = holder.GetCaptureData().GetActiveBackends();
313     CHECK(activeIds.size() == 2);
314     CHECK((activeIds.find(cpuAccId) != activeIds.end()));
315     CHECK((activeIds.find(gpuAccId) != activeIds.end()));
316 
317     recievedTimestamp = sendCounterPacket.GetTimestamps();
318 //
319     CHECK(recievedTimestamp[0].timestamp == period);
320     CHECK(recievedTimestamp[1].timestamp == period);
321 
322     CHECK(recievedTimestamp.size() == 2);
323     CHECK(recievedTimestamp[0].counterValues.size() == 2);
324     CHECK(recievedTimestamp[1].counterValues.size() == gpuCounters.size());
325 
326     CHECK(recievedTimestamp[0].counterValues[0].counterId == cpuCounters[0]);
327     CHECK(recievedTimestamp[0].counterValues[0].counterValue == 1u);
328     CHECK(recievedTimestamp[0].counterValues[1].counterId == cpuCounters[1]);
329     CHECK(recievedTimestamp[0].counterValues[1].counterValue == 2u);
330 
331     for (unsigned long i=0; i< gpuCounters.size(); ++i)
332     {
333         CHECK(recievedTimestamp[1].counterValues[i].counterId == gpuCounters[i]);
334         CHECK(recievedTimestamp[1].counterValues[i].counterValue == i + 1u);
335     }
336 
337     sendCounterPacket.ClearTimestamps();
338 
339     // Request all counters
340     std::vector<uint16_t> counterValues;
341     counterValues.insert(counterValues.begin(), cpuCounters.begin(), cpuCounters.end());
342     counterValues.insert(counterValues.begin(), gpuCounters.begin(), gpuCounters.end());
343 
344     periodicCounterSelectionCommandHandler(PacketWriter(period, counterValues));
345     periodicCounterCapture.Stop();
346 
347     activeIds = holder.GetCaptureData().GetActiveBackends();
348     CHECK(activeIds.size() == 2);
349     CHECK((activeIds.find(cpuAccId) != activeIds.end()));
350     CHECK((activeIds.find(gpuAccId) != activeIds.end()));
351 
352     recievedTimestamp = sendCounterPacket.GetTimestamps();
353 
354     CHECK(recievedTimestamp[0].counterValues.size() == cpuCounters.size());
355     for (unsigned long i=0; i< cpuCounters.size(); ++i)
356     {
357         CHECK(recievedTimestamp[0].counterValues[i].counterId == cpuCounters[i]);
358         CHECK(recievedTimestamp[0].counterValues[i].counterValue == i + 1u);
359     }
360 
361     CHECK(recievedTimestamp[1].counterValues.size() == gpuCounters.size());
362     for (unsigned long i=0; i< gpuCounters.size(); ++i)
363     {
364         CHECK(recievedTimestamp[1].counterValues[i].counterId == gpuCounters[i]);
365         CHECK(recievedTimestamp[1].counterValues[i].counterValue == i + 1u);
366     }
367     sendCounterPacket.ClearTimestamps();
368 
369     // Request random counters with duplicates and invalid counters
370     counterValues = {0, 0, 200, cpuCounters[2], gpuCounters[0],3 ,30, cpuCounters[0],cpuCounters[2], gpuCounters[1], 3,
371                      90, 0, 30, gpuCounters[0], gpuCounters[0]};
372 
373     periodicCounterSelectionCommandHandler(PacketWriter(period, counterValues));
374     periodicCounterCapture.Stop();
375 
376     activeIds = holder.GetCaptureData().GetActiveBackends();
377     CHECK(activeIds.size() == 2);
378     CHECK((activeIds.find(cpuAccId) != activeIds.end()));
379     CHECK((activeIds.find(gpuAccId) != activeIds.end()));
380 
381     recievedTimestamp = sendCounterPacket.GetTimestamps();
382 
383     CHECK(recievedTimestamp.size() == 2);
384 
385     CHECK(recievedTimestamp[0].counterValues.size() == 2);
386 
387     CHECK(recievedTimestamp[0].counterValues[0].counterId == cpuCounters[0]);
388     CHECK(recievedTimestamp[0].counterValues[0].counterValue == 1u);
389     CHECK(recievedTimestamp[0].counterValues[1].counterId == cpuCounters[2]);
390     CHECK(recievedTimestamp[0].counterValues[1].counterValue == 3u);
391 
392     CHECK(recievedTimestamp[1].counterValues.size() == 2);
393 
394     CHECK(recievedTimestamp[1].counterValues[0].counterId == gpuCounters[0]);
395     CHECK(recievedTimestamp[1].counterValues[0].counterValue == 1u);
396     CHECK(recievedTimestamp[1].counterValues[1].counterId == gpuCounters[1]);
397     CHECK(recievedTimestamp[1].counterValues[1].counterValue == 2u);
398 
399     sendCounterPacket.ClearTimestamps();
400 
401     // Request no counters
402     periodicCounterSelectionCommandHandler(PacketWriter(period, {}));
403     periodicCounterCapture.Stop();
404 
405     activeIds = holder.GetCaptureData().GetActiveBackends();
406     CHECK(activeIds.size() == 0);
407 
408     recievedTimestamp = sendCounterPacket.GetTimestamps();
409     CHECK(recievedTimestamp.size() == 0);
410 
411     sendCounterPacket.ClearTimestamps();
412 
413     // Request period of zero
414     periodicCounterSelectionCommandHandler(PacketWriter(0, counterValues));
415     periodicCounterCapture.Stop();
416 
417     activeIds = holder.GetCaptureData().GetActiveBackends();
418     CHECK(activeIds.size() == 0);
419 
420     recievedTimestamp = sendCounterPacket.GetTimestamps();
421     CHECK(recievedTimestamp.size() == 0);
422 }
423 
424 TEST_CASE("TestBackendCounterLogging")
425 {
426     std::stringstream ss;
427 
428     struct StreamRedirector
429     {
430     public:
StreamRedirectorStreamRedirector431         StreamRedirector(std::ostream &stream, std::streambuf *newStreamBuffer)
432                 : m_Stream(stream), m_BackupBuffer(m_Stream.rdbuf(newStreamBuffer))
433         {}
434 
~StreamRedirectorStreamRedirector435         ~StreamRedirector()
436         { m_Stream.rdbuf(m_BackupBuffer); }
437 
438     private:
439         std::ostream &m_Stream;
440         std::streambuf *m_BackupBuffer;
441     };
442 
443     Holder holder;
444     arm::pipe::PacketVersionResolver packetVersionResolver;
445     ProfilingStateMachine stateMachine;
446     ReadCounterVals readCounterVals;
447     StreamRedirector redirect(std::cout, ss.rdbuf());
448     CounterIdMap counterIdMap;
449     MockBackendSendCounterPacket sendCounterPacket;
450 
451     const std::string cpuAccId(GetComputeDeviceAsCString(armnn::Compute::CpuAcc));
452     const std::string gpuAccId(GetComputeDeviceAsCString(armnn::Compute::GpuAcc));
453 
454     ProfilingOptions options;
455     options.m_EnableProfiling = true;
456 
457     armnn::ArmNNProfilingServiceInitialiser initialiser;
458     std::unique_ptr<IProfilingService> profilingService = arm::pipe::IProfilingService::CreateProfilingService(
459         arm::pipe::MAX_ARMNN_COUNTER,
460         initialiser,
461         arm::pipe::ARMNN_SOFTWARE_INFO,
462         arm::pipe::ARMNN_SOFTWARE_VERSION,
463         arm::pipe::ARMNN_HARDWARE_VERSION);
464 
465     std::unique_ptr<IBackendProfiling> cpuBackendProfilingPtr =
466         std::make_unique<BackendProfiling>(options, *profilingService.get(), cpuAccId);
467 
468     std::shared_ptr<IBackendProfilingContext> cpuProfilingContextPtr =
469             std::make_shared<armnn::MockBackendProfilingContext>(cpuBackendProfilingPtr);
470 
471     std::unordered_map<std::string,
472             std::shared_ptr<IBackendProfilingContext>> backendProfilingContexts;
473 
474     uint16_t globalId = 5;
475     counterIdMap.RegisterMapping(globalId, 0, cpuAccId);
476     backendProfilingContexts[cpuAccId] = cpuProfilingContextPtr;
477 
478     PeriodicCounterCapture periodicCounterCapture(holder, sendCounterPacket, readCounterVals,
479                                                   counterIdMap, backendProfilingContexts);
480 
481     uint16_t maxArmnnCounterId = 4;
482 
483     PeriodicCounterSelectionCommandHandler periodicCounterSelectionCommandHandler(0,
484                                                   4,
485                                                   packetVersionResolver.ResolvePacketVersion(0, 4).GetEncodedValue(),
486                                                   backendProfilingContexts,
487                                                   counterIdMap,
488                                                   holder,
489                                                   maxArmnnCounterId,
490                                                   periodicCounterCapture,
491                                                   readCounterVals,
492                                                   sendCounterPacket,
493                                                   stateMachine);
494 
495     stateMachine.TransitionToState(ProfilingState::NotConnected);
496     stateMachine.TransitionToState(ProfilingState::WaitingForAck);
497     stateMachine.TransitionToState(ProfilingState::Active);
498 
499     uint32_t period = 15939u;
500 
501     arm::pipe::SetAllLoggingSinks(true, false, false);
502     arm::pipe::SetLogFilter(arm::pipe::LogSeverity::Warning);
503     periodicCounterSelectionCommandHandler(PacketWriter(period, {5}));
504     periodicCounterCapture.Stop();
505     arm::pipe::SetLogFilter(arm::pipe::LogSeverity::Fatal);
506 
507     CHECK(ss.str().find("ActivateCounters example test error") != std::string::npos);
508 }
509 
510 TEST_CASE("BackendProfilingContextGetSendTimelinePacket")
511 {
512     arm::pipe::LogLevelSwapper logLevelSwapper(arm::pipe::LogSeverity::Fatal);
513 
514     // Reset the profiling service to the uninitialized state
515     armnn::IRuntime::CreationOptions options;
516     options.m_ProfilingOptions.m_EnableProfiling = true;
517 
518     armnn::ArmNNProfilingServiceInitialiser psInitialiser;
519     std::unique_ptr<IProfilingService> profilingService = arm::pipe::IProfilingService::CreateProfilingService(
520         arm::pipe::MAX_ARMNN_COUNTER,
521         psInitialiser,
522         arm::pipe::ARMNN_SOFTWARE_INFO,
523         arm::pipe::ARMNN_SOFTWARE_VERSION,
524         arm::pipe::ARMNN_HARDWARE_VERSION);
525 
526     profilingService->ConfigureProfilingService(
527         ConvertExternalProfilingOptions(options.m_ProfilingOptions), true);
528 
529     armnn::MockBackendInitialiser initialiser;
530     // Create a runtime. During this the mock backend will be registered and context returned.
531     armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
532     armnn::MockBackendProfilingService mockProfilingService = armnn::MockBackendProfilingService::Instance();
533     armnn::MockBackendProfilingContext* mockBackEndProfilingContext = mockProfilingService.GetContext();
534     // Check that there is a valid context set.
535     CHECK(mockBackEndProfilingContext);
536     armnn::IBackendInternal::IBackendProfilingPtr& backendProfilingIface =
537         mockBackEndProfilingContext->GetBackendProfiling();
538     CHECK(backendProfilingIface);
539 
540     // Now for the meat of the test. We're just going to send a random packet and make sure there
541     // are no exceptions or errors. The sending of packets is already tested in SendTimelinePacketTests.
542     std::unique_ptr<ISendTimelinePacket> timelinePacket =
543         backendProfilingIface->GetSendTimelinePacket();
544     // Send TimelineEntityClassBinaryPacket
545     const uint64_t entityBinaryPacketProfilingGuid = 123456u;
546     timelinePacket->SendTimelineEntityBinaryPacket(entityBinaryPacketProfilingGuid);
547     timelinePacket->Commit();
548 
549     // Reset the profiling servie after the test.
550     options.m_ProfilingOptions.m_EnableProfiling = false;
551     profilingService->ResetExternalProfilingOptions(
552         ConvertExternalProfilingOptions(options.m_ProfilingOptions), true);
553 }
554 
555 TEST_CASE("GetProfilingGuidGenerator")
556 {
557     arm::pipe::LogLevelSwapper logLevelSwapper(arm::pipe::LogSeverity::Fatal);
558 
559     // Reset the profiling service to the uninitialized state
560     armnn::IRuntime::CreationOptions options;
561     options.m_ProfilingOptions.m_EnableProfiling = true;
562 
563     armnn::MockBackendInitialiser initialiser;
564     // Create a runtime. During this the mock backend will be registered and context returned.
565     armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
566     armnn::MockBackendProfilingService mockProfilingService = armnn::MockBackendProfilingService::Instance();
567     armnn::MockBackendProfilingContext *mockBackEndProfilingContext = mockProfilingService.GetContext();
568     // Check that there is a valid context set.
569     CHECK(mockBackEndProfilingContext);
570     armnn::IBackendInternal::IBackendProfilingPtr& backendProfilingIface =
571         mockBackEndProfilingContext->GetBackendProfiling();
572     CHECK(backendProfilingIface);
573 
574     // Get the Guid generator and check the getting two Guid's results in the second being greater than the first.
575     IProfilingGuidGenerator& guidGenerator = backendProfilingIface->GetProfilingGuidGenerator();
576     const ProfilingDynamicGuid& firstGuid = guidGenerator.NextGuid();
577     const ProfilingDynamicGuid& secondGuid = guidGenerator.NextGuid();
578     CHECK(secondGuid > firstGuid);
579 
580     // Reset the profiling servie after the test.
581     options.m_ProfilingOptions.m_EnableProfiling = false;
582 }
583 
584 }
585