Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 1 | // |
| 2 | // Copyright © 2017 Arm Ltd. All rights reserved. |
| 3 | // SPDX-License-Identifier: MIT |
| 4 | // |
| 5 | |
Matteo Martincigh | 6598427 | 2019-10-17 13:26:21 +0100 | [diff] [blame] | 6 | #include <CommandHandlerRegistry.hpp> |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame] | 7 | #include <ConnectionHandler.hpp> |
Keith Davis | 3201eea | 2019-10-24 17:30:41 +0100 | [diff] [blame] | 8 | #include <DirectoryCaptureCommandHandler.hpp> |
Finn Williams | 0c8cb99 | 2020-05-07 10:38:15 +0100 | [diff] [blame] | 9 | #include <GatordMockService.hpp> |
Finn Williams | af1c63b | 2020-03-23 18:01:49 +0000 | [diff] [blame] | 10 | #include <LabelsAndEventClasses.hpp> |
Finn Williams | af1c63b | 2020-03-23 18:01:49 +0000 | [diff] [blame] | 11 | #include <ProfilingService.hpp> |
Finn Williams | af1c63b | 2020-03-23 18:01:49 +0000 | [diff] [blame] | 12 | #include <TimelinePacketWriterFactory.hpp> |
Finn Williams | 8a2b468 | 2020-02-26 10:25:26 +0000 | [diff] [blame] | 13 | |
Matteo Martincigh | cdfb941 | 2019-11-08 11:23:06 +0000 | [diff] [blame] | 14 | #include <TimelineDirectoryCaptureCommandHandler.hpp> |
Finn Williams | e6a2ccd | 2020-02-27 16:21:41 +0000 | [diff] [blame] | 15 | #include <TimelineDecoder.hpp> |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 16 | |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 17 | #include <Runtime.hpp> |
Finn Williams | 0c8cb99 | 2020-05-07 10:38:15 +0100 | [diff] [blame] | 18 | |
| 19 | #include <MockBackend.hpp> |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 20 | |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 21 | #include <boost/cast.hpp> |
| 22 | #include <boost/test/test_tools.hpp> |
| 23 | #include <boost/test/unit_test_suite.hpp> |
| 24 | |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame] | 25 | |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 26 | BOOST_AUTO_TEST_SUITE(GatordMockTests) |
| 27 | |
| 28 | using namespace armnn; |
Finn Williams | e6a2ccd | 2020-02-27 16:21:41 +0000 | [diff] [blame] | 29 | using namespace std::this_thread; |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 30 | using namespace std::chrono_literals; |
| 31 | |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 32 | BOOST_AUTO_TEST_CASE(CounterCaptureHandlingTest) |
| 33 | { |
| 34 | using boost::numeric_cast; |
| 35 | |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 36 | profiling::PacketVersionResolver packetVersionResolver; |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 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 | |
Finn Williams | c626345 | 2019-10-11 18:25:07 +0100 | [diff] [blame] | 55 | uint64_t time2 = time + 5000; |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 56 | |
| 57 | // UniqueData required for Packet class |
| 58 | std::unique_ptr<unsigned char[]> uniqueData1 = std::make_unique<unsigned char[]>(dataLength); |
Colm Donelan | b682d84 | 2019-10-16 12:24:20 +0100 | [diff] [blame] | 59 | unsigned char* data1 = reinterpret_cast<unsigned char*>(uniqueData1.get()); |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 60 | |
| 61 | std::unique_ptr<unsigned char[]> uniqueData2 = std::make_unique<unsigned char[]>(dataLength); |
Colm Donelan | b682d84 | 2019-10-16 12:24:20 +0100 | [diff] [blame] | 62 | unsigned char* data2 = reinterpret_cast<unsigned char*>(uniqueData2.get()); |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 63 | |
| 64 | uint32_t sizeOfUint64 = numeric_cast<uint32_t>(sizeof(uint64_t)); |
| 65 | uint32_t sizeOfUint32 = numeric_cast<uint32_t>(sizeof(uint32_t)); |
| 66 | uint32_t sizeOfUint16 = numeric_cast<uint32_t>(sizeof(uint16_t)); |
| 67 | // Offset index to point to mem address |
| 68 | uint32_t offset = 0; |
| 69 | |
| 70 | profiling::WriteUint64(data1, offset, time); |
| 71 | offset += sizeOfUint64; |
| 72 | for (const auto& pair : indexValuePairs) |
| 73 | { |
| 74 | profiling::WriteUint16(data1, offset, pair.first); |
| 75 | offset += sizeOfUint16; |
| 76 | profiling::WriteUint32(data1, offset, pair.second); |
| 77 | offset += sizeOfUint32; |
| 78 | } |
| 79 | |
| 80 | offset = 0; |
| 81 | |
| 82 | profiling::WriteUint64(data2, offset, time2); |
| 83 | offset += sizeOfUint64; |
| 84 | for (const auto& pair : indexValuePairs) |
| 85 | { |
| 86 | profiling::WriteUint16(data2, offset, pair.first); |
| 87 | offset += sizeOfUint16; |
| 88 | profiling::WriteUint32(data2, offset, pair.second); |
| 89 | offset += sizeOfUint32; |
| 90 | } |
| 91 | |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 92 | uint32_t headerWord1 = packetVersionResolver.ResolvePacketVersion(0, 4).GetEncodedValue(); |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 93 | // Create packet to send through to the command functor |
| 94 | profiling::Packet packet1(headerWord1, dataLength, uniqueData1); |
| 95 | profiling::Packet packet2(headerWord1, dataLength, uniqueData2); |
| 96 | |
Keith Davis | 3201eea | 2019-10-24 17:30:41 +0100 | [diff] [blame] | 97 | gatordmock::PeriodicCounterCaptureCommandHandler commandHandler(0, 4, headerWord1, true); |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 98 | |
| 99 | // Simulate two separate packets coming in to calculate period |
| 100 | commandHandler(packet1); |
| 101 | commandHandler(packet2); |
| 102 | |
Narumol Prangnawarat | ac2770a | 2020-04-01 16:51:23 +0100 | [diff] [blame] | 103 | ARMNN_ASSERT(commandHandler.m_CurrentPeriodValue == 5000); |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 104 | |
| 105 | for (size_t i = 0; i < commandHandler.m_CounterCaptureValues.m_Uids.size(); ++i) |
| 106 | { |
Narumol Prangnawarat | ac2770a | 2020-04-01 16:51:23 +0100 | [diff] [blame] | 107 | ARMNN_ASSERT(commandHandler.m_CounterCaptureValues.m_Uids[i] == i); |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 108 | } |
| 109 | } |
| 110 | |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 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 | BOOST_FAIL("Timeout: " + errorMsg); |
| 119 | } |
| 120 | std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime)); |
| 121 | timeSlept += sleepTime; |
| 122 | } |
| 123 | } |
Finn Williams | af1c63b | 2020-03-23 18:01:49 +0000 | [diff] [blame] | 124 | |
| 125 | void CheckTimelineDirectory(timelinedecoder::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); |
Jim Flynn | 1fdeb99 | 2020-07-09 07:28:37 +0100 | [diff] [blame^] | 130 | uint32_t threadId_size = sizeof(int); |
Finn Williams | af1c63b | 2020-03-23 18:01:49 +0000 | [diff] [blame] | 131 | |
| 132 | profiling::BufferManager bufferManager(5); |
| 133 | profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); |
| 134 | |
| 135 | std::unique_ptr<profiling::ISendTimelinePacket> sendTimelinePacket = |
| 136 | timelinePacketWriterFactory.GetSendTimelinePacket(); |
| 137 | |
| 138 | sendTimelinePacket->SendTimelineMessageDirectoryPackage(); |
| 139 | sendTimelinePacket->Commit(); |
| 140 | |
| 141 | std::vector<profiling::SwTraceMessage> swTraceBufferMessages; |
| 142 | |
| 143 | unsigned int offset = uint32_t_size * 2; |
| 144 | |
| 145 | std::unique_ptr<profiling::IPacketBuffer> packetBuffer = bufferManager.GetReadableBuffer(); |
| 146 | |
| 147 | uint8_t readStreamVersion = ReadUint8(packetBuffer, offset); |
| 148 | BOOST_CHECK(readStreamVersion == 4); |
| 149 | offset += uint8_t_size; |
| 150 | uint8_t readPointerBytes = ReadUint8(packetBuffer, offset); |
| 151 | BOOST_CHECK(readPointerBytes == uint64_t_size); |
| 152 | offset += uint8_t_size; |
| 153 | uint8_t readThreadIdBytes = ReadUint8(packetBuffer, offset); |
| 154 | BOOST_CHECK(readThreadIdBytes == threadId_size); |
| 155 | offset += uint8_t_size; |
| 156 | |
| 157 | uint32_t declarationSize = profiling::ReadUint32(packetBuffer, offset); |
| 158 | offset += uint32_t_size; |
| 159 | for(uint32_t i = 0; i < declarationSize; ++i) |
| 160 | { |
| 161 | swTraceBufferMessages.push_back(profiling::ReadSwTraceMessage(packetBuffer->GetReadableData(), offset)); |
| 162 | } |
| 163 | |
| 164 | for(uint32_t index = 0; index < declarationSize; ++index) |
| 165 | { |
| 166 | profiling::SwTraceMessage& bufferMessage = swTraceBufferMessages[index]; |
| 167 | profiling::SwTraceMessage& handlerMessage = commandHandler.m_SwTraceMessages[index]; |
| 168 | |
| 169 | BOOST_CHECK(bufferMessage.m_Name == handlerMessage.m_Name); |
| 170 | BOOST_CHECK(bufferMessage.m_UiName == handlerMessage.m_UiName); |
| 171 | BOOST_CHECK(bufferMessage.m_Id == handlerMessage.m_Id); |
| 172 | |
| 173 | BOOST_CHECK(bufferMessage.m_ArgTypes.size() == handlerMessage.m_ArgTypes.size()); |
| 174 | for(uint32_t i = 0; i < bufferMessage.m_ArgTypes.size(); ++i) |
| 175 | { |
| 176 | BOOST_CHECK(bufferMessage.m_ArgTypes[i] == handlerMessage.m_ArgTypes[i]); |
| 177 | } |
| 178 | |
| 179 | BOOST_CHECK(bufferMessage.m_ArgNames.size() == handlerMessage.m_ArgNames.size()); |
| 180 | for(uint32_t i = 0; i < bufferMessage.m_ArgNames.size(); ++i) |
| 181 | { |
| 182 | BOOST_CHECK(bufferMessage.m_ArgNames[i] == handlerMessage.m_ArgNames[i]); |
| 183 | } |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | void CheckTimelinePackets(timelinedecoder::TimelineDecoder& timelineDecoder) |
| 188 | { |
| 189 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[0].m_Guid == profiling::LabelsAndEventClasses::NAME_GUID); |
| 190 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[0].m_Name == profiling::LabelsAndEventClasses::NAME_LABEL); |
| 191 | |
| 192 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[1].m_Guid == profiling::LabelsAndEventClasses::TYPE_GUID); |
| 193 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[1].m_Name == profiling::LabelsAndEventClasses::TYPE_LABEL); |
| 194 | |
| 195 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[2].m_Guid == profiling::LabelsAndEventClasses::INDEX_GUID); |
| 196 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[2].m_Name == profiling::LabelsAndEventClasses::INDEX_LABEL); |
| 197 | |
| 198 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[3].m_Guid == profiling::LabelsAndEventClasses::BACKENDID_GUID); |
| 199 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[3].m_Name == profiling::LabelsAndEventClasses::BACKENDID_LABEL); |
| 200 | |
| 201 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[4].m_Guid == profiling::LabelsAndEventClasses::LAYER_GUID); |
| 202 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[4].m_Name == profiling::LabelsAndEventClasses::LAYER); |
| 203 | |
| 204 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[5].m_Guid == profiling::LabelsAndEventClasses::WORKLOAD_GUID); |
| 205 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[5].m_Name == profiling::LabelsAndEventClasses::WORKLOAD); |
| 206 | |
| 207 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[6].m_Guid == profiling::LabelsAndEventClasses::NETWORK_GUID); |
| 208 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[6].m_Name == profiling::LabelsAndEventClasses::NETWORK); |
| 209 | |
| 210 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[7].m_Guid == profiling::LabelsAndEventClasses::CONNECTION_GUID); |
| 211 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[7].m_Name == profiling::LabelsAndEventClasses::CONNECTION); |
| 212 | |
| 213 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[8].m_Guid == profiling::LabelsAndEventClasses::INFERENCE_GUID); |
| 214 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[8].m_Name == profiling::LabelsAndEventClasses::INFERENCE); |
| 215 | |
| 216 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[9].m_Guid == |
| 217 | profiling::LabelsAndEventClasses::WORKLOAD_EXECUTION_GUID); |
| 218 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels[9].m_Name == profiling::LabelsAndEventClasses::WORKLOAD_EXECUTION); |
| 219 | |
| 220 | BOOST_CHECK(timelineDecoder.GetModel().m_EventClasses[0].m_Guid == |
| 221 | profiling::LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS); |
| 222 | BOOST_CHECK(timelineDecoder.GetModel().m_EventClasses[1].m_Guid == |
| 223 | profiling::LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS); |
| 224 | } |
| 225 | |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 226 | BOOST_AUTO_TEST_CASE(GatorDMockEndToEnd) |
| 227 | { |
| 228 | // The purpose of this test is to setup both sides of the profiling service and get to the point of receiving |
| 229 | // performance data. |
| 230 | |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 231 | // Setup the mock service to bind to the UDS. |
| 232 | std::string udsNamespace = "gatord_namespace"; |
Finn Williams | e6a2ccd | 2020-02-27 16:21:41 +0000 | [diff] [blame] | 233 | |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame] | 234 | BOOST_CHECK_NO_THROW(armnnProfiling::ConnectionHandler connectionHandler(udsNamespace, false)); |
Finn Williams | e6a2ccd | 2020-02-27 16:21:41 +0000 | [diff] [blame] | 235 | |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame] | 236 | armnnProfiling::ConnectionHandler connectionHandler(udsNamespace, false); |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 237 | |
| 238 | // Enable the profiling service. |
Narumol Prangnawarat | 85ad78c | 2019-11-18 15:34:23 +0000 | [diff] [blame] | 239 | armnn::IRuntime::CreationOptions::ExternalProfilingOptions options; |
Finn Williams | d7fcafa | 2020-04-23 17:55:18 +0100 | [diff] [blame] | 240 | options.m_EnableProfiling = true; |
| 241 | options.m_TimelineEnabled = true; |
| 242 | |
Sadik Armagan | 3184c90 | 2020-03-18 10:57:30 +0000 | [diff] [blame] | 243 | armnn::profiling::ProfilingService profilingService; |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 244 | profilingService.ResetExternalProfilingOptions(options, true); |
| 245 | |
| 246 | // Bring the profiling service to the "WaitingForAck" state |
| 247 | BOOST_CHECK(profilingService.GetCurrentState() == profiling::ProfilingState::Uninitialised); |
| 248 | profilingService.Update(); |
| 249 | BOOST_CHECK(profilingService.GetCurrentState() == profiling::ProfilingState::NotConnected); |
| 250 | profilingService.Update(); |
| 251 | |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame] | 252 | // Connect the profiling service |
| 253 | auto basePipeServer = connectionHandler.GetNewBasePipeServer(false); |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 254 | |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame] | 255 | // Connect the profiling service to the mock Gatord. |
| 256 | gatordmock::GatordMockService mockService(std::move(basePipeServer), false); |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 257 | |
| 258 | timelinedecoder::TimelineDecoder& timelineDecoder = mockService.GetTimelineDecoder(); |
| 259 | profiling::DirectoryCaptureCommandHandler& directoryCaptureCommandHandler = |
| 260 | mockService.GetDirectoryCaptureCommandHandler(); |
Finn Williams | e6a2ccd | 2020-02-27 16:21:41 +0000 | [diff] [blame] | 261 | |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 262 | // Give the profiling service sending thread time start executing and send the stream metadata. |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 263 | WaitFor([&](){return profilingService.GetCurrentState() == profiling::ProfilingState::WaitingForAck;}, |
| 264 | "Profiling service did not switch to WaitingForAck state"); |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 265 | |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 266 | profilingService.Update(); |
| 267 | // Read the stream metadata on the mock side. |
| 268 | if (!mockService.WaitForStreamMetaData()) |
| 269 | { |
| 270 | BOOST_FAIL("Failed to receive StreamMetaData"); |
| 271 | } |
| 272 | // Send Ack from GatorD |
| 273 | mockService.SendConnectionAck(); |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 274 | // And start to listen for packets |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 275 | mockService.LaunchReceivingThread(); |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 276 | |
| 277 | WaitFor([&](){return profilingService.GetCurrentState() == profiling::ProfilingState::Active;}, |
| 278 | "Profiling service did not switch to Active state"); |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 279 | |
Finn Williams | af1c63b | 2020-03-23 18:01:49 +0000 | [diff] [blame] | 280 | // As part of the default startup of the profiling service a counter directory packet will be sent. |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 281 | WaitFor([&](){return directoryCaptureCommandHandler.ParsedCounterDirectory();}, |
| 282 | "MockGatord did not receive counter directory packet"); |
Finn Williams | af1c63b | 2020-03-23 18:01:49 +0000 | [diff] [blame] | 283 | |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 284 | // Following that we will receive a collection of well known timeline labels and event classes |
| 285 | WaitFor([&](){return timelineDecoder.GetModel().m_EventClasses.size() >= 2;}, |
| 286 | "MockGatord did not receive well known timeline labels and event classes"); |
Finn Williams | af1c63b | 2020-03-23 18:01:49 +0000 | [diff] [blame] | 287 | |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 288 | CheckTimelineDirectory(mockService.GetTimelineDirectoryCaptureCommandHandler()); |
Finn Williams | af1c63b | 2020-03-23 18:01:49 +0000 | [diff] [blame] | 289 | // Verify the commonly used timeline packets sent when the profiling service enters the active state |
| 290 | CheckTimelinePackets(timelineDecoder); |
| 291 | |
Keith Davis | 3201eea | 2019-10-24 17:30:41 +0100 | [diff] [blame] | 292 | const profiling::ICounterDirectory& serviceCounterDirectory = profilingService.GetCounterDirectory(); |
| 293 | const profiling::ICounterDirectory& receivedCounterDirectory = directoryCaptureCommandHandler.GetCounterDirectory(); |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 294 | |
Finn Williams | af1c63b | 2020-03-23 18:01:49 +0000 | [diff] [blame] | 295 | // Compare the basics of the counter directory from the service and the one we received over the wire. |
| 296 | BOOST_CHECK(serviceCounterDirectory.GetDeviceCount() == receivedCounterDirectory.GetDeviceCount()); |
| 297 | BOOST_CHECK(serviceCounterDirectory.GetCounterSetCount() == receivedCounterDirectory.GetCounterSetCount()); |
| 298 | BOOST_CHECK(serviceCounterDirectory.GetCategoryCount() == receivedCounterDirectory.GetCategoryCount()); |
| 299 | BOOST_CHECK(serviceCounterDirectory.GetCounterCount() == receivedCounterDirectory.GetCounterCount()); |
Keith Davis | 3201eea | 2019-10-24 17:30:41 +0100 | [diff] [blame] | 300 | |
| 301 | receivedCounterDirectory.GetDeviceCount(); |
| 302 | serviceCounterDirectory.GetDeviceCount(); |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 303 | |
| 304 | const profiling::Devices& serviceDevices = serviceCounterDirectory.GetDevices(); |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 305 | for (auto& device : serviceDevices) |
| 306 | { |
Keith Davis | 3201eea | 2019-10-24 17:30:41 +0100 | [diff] [blame] | 307 | // Find the same device in the received counter directory. |
| 308 | auto foundDevice = receivedCounterDirectory.GetDevices().find(device.second->m_Uid); |
| 309 | BOOST_CHECK(foundDevice != receivedCounterDirectory.GetDevices().end()); |
| 310 | BOOST_CHECK(device.second->m_Name.compare((*foundDevice).second->m_Name) == 0); |
| 311 | BOOST_CHECK(device.second->m_Cores == (*foundDevice).second->m_Cores); |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 312 | } |
| 313 | |
Keith Davis | 3201eea | 2019-10-24 17:30:41 +0100 | [diff] [blame] | 314 | const profiling::CounterSets& serviceCounterSets = serviceCounterDirectory.GetCounterSets(); |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 315 | for (auto& counterSet : serviceCounterSets) |
| 316 | { |
Keith Davis | 3201eea | 2019-10-24 17:30:41 +0100 | [diff] [blame] | 317 | // Find the same counter set in the received counter directory. |
| 318 | auto foundCounterSet = receivedCounterDirectory.GetCounterSets().find(counterSet.second->m_Uid); |
| 319 | BOOST_CHECK(foundCounterSet != receivedCounterDirectory.GetCounterSets().end()); |
| 320 | BOOST_CHECK(counterSet.second->m_Name.compare((*foundCounterSet).second->m_Name) == 0); |
| 321 | BOOST_CHECK(counterSet.second->m_Count == (*foundCounterSet).second->m_Count); |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 322 | } |
| 323 | |
| 324 | const profiling::Categories& serviceCategories = serviceCounterDirectory.GetCategories(); |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 325 | for (auto& category : serviceCategories) |
| 326 | { |
Keith Davis | 3201eea | 2019-10-24 17:30:41 +0100 | [diff] [blame] | 327 | for (auto& receivedCategory : receivedCounterDirectory.GetCategories()) |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 328 | { |
Keith Davis | 3201eea | 2019-10-24 17:30:41 +0100 | [diff] [blame] | 329 | if (receivedCategory->m_Name.compare(category->m_Name) == 0) |
| 330 | { |
| 331 | // We've found the matching category. |
Keith Davis | 3201eea | 2019-10-24 17:30:41 +0100 | [diff] [blame] | 332 | // Now look at the interiors of the counters. Start by sorting them. |
| 333 | std::sort(category->m_Counters.begin(), category->m_Counters.end()); |
| 334 | std::sort(receivedCategory->m_Counters.begin(), receivedCategory->m_Counters.end()); |
| 335 | // When comparing uid's here we need to translate them. |
| 336 | std::function<bool(const uint16_t&, const uint16_t&)> comparator = |
| 337 | [&directoryCaptureCommandHandler](const uint16_t& first, const uint16_t& second) { |
| 338 | uint16_t translated = directoryCaptureCommandHandler.TranslateUIDCopyToOriginal(second); |
| 339 | if (translated == first) |
| 340 | { |
| 341 | return true; |
| 342 | } |
| 343 | return false; |
| 344 | }; |
| 345 | // Then let vector == do the work. |
| 346 | BOOST_CHECK(std::equal(category->m_Counters.begin(), category->m_Counters.end(), |
| 347 | receivedCategory->m_Counters.begin(), comparator)); |
| 348 | break; |
| 349 | } |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 350 | } |
Keith Davis | 3201eea | 2019-10-24 17:30:41 +0100 | [diff] [blame] | 351 | } |
| 352 | |
| 353 | // Finally check the content of the counters. |
| 354 | const profiling::Counters& receivedCounters = receivedCounterDirectory.GetCounters(); |
| 355 | for (auto& receivedCounter : receivedCounters) |
| 356 | { |
| 357 | // Translate the Uid and find the corresponding counter in the original counter directory. |
| 358 | // Note we can't check m_MaxCounterUid here as it will likely differ between the two counter directories. |
| 359 | uint16_t translated = directoryCaptureCommandHandler.TranslateUIDCopyToOriginal(receivedCounter.first); |
| 360 | const profiling::Counter* serviceCounter = serviceCounterDirectory.GetCounter(translated); |
| 361 | BOOST_CHECK(serviceCounter->m_DeviceUid == receivedCounter.second->m_DeviceUid); |
| 362 | BOOST_CHECK(serviceCounter->m_Name.compare(receivedCounter.second->m_Name) == 0); |
| 363 | BOOST_CHECK(serviceCounter->m_CounterSetUid == receivedCounter.second->m_CounterSetUid); |
| 364 | BOOST_CHECK(serviceCounter->m_Multiplier == receivedCounter.second->m_Multiplier); |
| 365 | BOOST_CHECK(serviceCounter->m_Interpolation == receivedCounter.second->m_Interpolation); |
| 366 | BOOST_CHECK(serviceCounter->m_Class == receivedCounter.second->m_Class); |
| 367 | BOOST_CHECK(serviceCounter->m_Units.compare(receivedCounter.second->m_Units) == 0); |
| 368 | BOOST_CHECK(serviceCounter->m_Description.compare(receivedCounter.second->m_Description) == 0); |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 369 | } |
| 370 | |
| 371 | mockService.WaitForReceivingThread(); |
| 372 | options.m_EnableProfiling = false; |
| 373 | profilingService.ResetExternalProfilingOptions(options, true); |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 374 | // Future tests here will add counters to the ProfilingService, increment values and examine |
| 375 | // PeriodicCounterCapture data received. These are yet to be integrated. |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 376 | } |
| 377 | |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 378 | BOOST_AUTO_TEST_CASE(GatorDMockTimeLineActivation) |
| 379 | { |
Finn Williams | 0c32ccf | 2020-05-12 13:37:06 +0100 | [diff] [blame] | 380 | // This test requires the CpuRef backend to be enabled |
| 381 | if(!BackendRegistryInstance().IsBackendRegistered("CpuRef")) |
| 382 | { |
| 383 | return; |
| 384 | } |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 385 | armnn::MockBackendInitialiser initialiser; |
| 386 | // Setup the mock service to bind to the UDS. |
| 387 | std::string udsNamespace = "gatord_namespace"; |
| 388 | |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame] | 389 | armnnProfiling::ConnectionHandler connectionHandler(udsNamespace, false); |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 390 | |
| 391 | armnn::IRuntime::CreationOptions options; |
| 392 | options.m_ProfilingOptions.m_EnableProfiling = true; |
Finn Williams | d7fcafa | 2020-04-23 17:55:18 +0100 | [diff] [blame] | 393 | options.m_ProfilingOptions.m_TimelineEnabled = true; |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 394 | armnn::Runtime runtime(options); |
| 395 | |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame] | 396 | auto basePipeServer = connectionHandler.GetNewBasePipeServer(false); |
| 397 | gatordmock::GatordMockService mockService(std::move(basePipeServer), false); |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 398 | |
| 399 | // Read the stream metadata on the mock side. |
| 400 | if (!mockService.WaitForStreamMetaData()) |
| 401 | { |
| 402 | BOOST_FAIL("Failed to receive StreamMetaData"); |
| 403 | } |
| 404 | |
| 405 | armnn::MockBackendProfilingService mockProfilingService = armnn::MockBackendProfilingService::Instance(); |
| 406 | armnn::MockBackendProfilingContext *mockBackEndProfilingContext = mockProfilingService.GetContext(); |
| 407 | |
| 408 | // Send Ack from GatorD |
| 409 | mockService.SendConnectionAck(); |
| 410 | // And start to listen for packets |
| 411 | mockService.LaunchReceivingThread(); |
| 412 | |
| 413 | // Build and optimize a simple network while we wait |
| 414 | INetworkPtr net(INetwork::Create()); |
| 415 | |
| 416 | IConnectableLayer* input = net->AddInputLayer(0, "input"); |
| 417 | |
| 418 | NormalizationDescriptor descriptor; |
| 419 | IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor, "normalization"); |
| 420 | |
| 421 | IConnectableLayer* output = net->AddOutputLayer(0, "output"); |
| 422 | |
| 423 | input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0)); |
| 424 | normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0)); |
| 425 | |
| 426 | input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32)); |
| 427 | normalize->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32)); |
| 428 | |
| 429 | std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef }; |
| 430 | IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime.GetDeviceSpec()); |
| 431 | |
| 432 | WaitFor([&](){return mockService.GetDirectoryCaptureCommandHandler().ParsedCounterDirectory();}, |
| 433 | "MockGatord did not receive counter directory packet"); |
| 434 | |
| 435 | timelinedecoder::TimelineDecoder& timelineDecoder = mockService.GetTimelineDecoder(); |
| 436 | |
| 437 | WaitFor([&](){return timelineDecoder.GetModel().m_EventClasses.size() >= 2;}, |
| 438 | "MockGatord did not receive well known timeline labels"); |
| 439 | |
Finn Williams | fe5a24b | 2020-04-09 16:05:28 +0100 | [diff] [blame] | 440 | WaitFor([&](){return timelineDecoder.GetModel().m_Entities.size() >= 1;}, |
| 441 | "MockGatord did not receive mock backend test entity"); |
| 442 | |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 443 | // Packets we expect from SendWellKnownLabelsAndEventClassesTest |
Finn Williams | fe5a24b | 2020-04-09 16:05:28 +0100 | [diff] [blame] | 444 | BOOST_CHECK(timelineDecoder.GetModel().m_Entities.size() == 1); |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 445 | BOOST_CHECK(timelineDecoder.GetModel().m_EventClasses.size() == 2); |
Jan Eilers | fd55dc9 | 2020-06-25 12:00:38 +0100 | [diff] [blame] | 446 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels.size() == 14); |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 447 | BOOST_CHECK(timelineDecoder.GetModel().m_Relationships.size() == 0); |
| 448 | BOOST_CHECK(timelineDecoder.GetModel().m_Events.size() == 0); |
| 449 | |
| 450 | mockService.SendDeactivateTimelinePacket(); |
| 451 | |
| 452 | WaitFor([&](){return !mockBackEndProfilingContext->TimelineReportingEnabled();}, |
| 453 | "Timeline packets were not deactivated"); |
| 454 | |
| 455 | // Load the network into runtime now that timeline reporting is disabled |
| 456 | armnn::NetworkId netId; |
| 457 | runtime.LoadNetwork(netId, std::move(optNet)); |
| 458 | |
| 459 | // Now activate timeline packets |
| 460 | mockService.SendActivateTimelinePacket(); |
| 461 | |
| 462 | WaitFor([&](){return mockBackEndProfilingContext->TimelineReportingEnabled();}, |
| 463 | "Timeline packets were not activated"); |
| 464 | |
| 465 | // Once timeline packets have been reactivated the ActivateTimelineReportingCommandHandler will resend the |
| 466 | // SendWellKnownLabelsAndEventClasses and then send the structure of any loaded networks |
| 467 | WaitFor([&](){return timelineDecoder.GetModel().m_Labels.size() >= 24;}, |
| 468 | "MockGatord did not receive well known timeline labels"); |
| 469 | |
Jan Eilers | fd55dc9 | 2020-06-25 12:00:38 +0100 | [diff] [blame] | 470 | // Packets we expect from SendWellKnownLabelsAndEventClassesTest * 2 + network above (input, norm, backend, output) |
Finn Williams | fe5a24b | 2020-04-09 16:05:28 +0100 | [diff] [blame] | 471 | BOOST_CHECK(timelineDecoder.GetModel().m_Entities.size() == 6); |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 472 | BOOST_CHECK(timelineDecoder.GetModel().m_EventClasses.size() == 4); |
Jan Eilers | fd55dc9 | 2020-06-25 12:00:38 +0100 | [diff] [blame] | 473 | BOOST_CHECK(timelineDecoder.GetModel().m_Labels.size() == 32); |
Finn Williams | 0a336dc | 2020-05-11 15:39:58 +0100 | [diff] [blame] | 474 | BOOST_CHECK(timelineDecoder.GetModel().m_Relationships.size() == 17); |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 475 | BOOST_CHECK(timelineDecoder.GetModel().m_Events.size() == 0); |
| 476 | |
| 477 | mockService.WaitForReceivingThread(); |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 478 | GetProfilingService(&runtime).Disconnect(); |
| 479 | } |
| 480 | |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 481 | BOOST_AUTO_TEST_SUITE_END() |