2 // Copyright © 2019 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
6 #include <Filesystem.hpp>
7 #include <ProfilingService.hpp>
9 #include "PrintPacketHeaderHandler.hpp"
10 #include "TestTimelinePacketHandler.hpp"
12 #include <boost/filesystem.hpp>
13 #include <boost/numeric/conversion/cast.hpp>
14 #include <boost/test/unit_test.hpp>
20 using namespace armnn::profiling;
21 using namespace armnn;
23 using namespace std::chrono_literals;
25 class FileOnlyHelperService : public ProfilingService
28 // Wait for a notification from the send thread
29 bool WaitForPacketsSent(uint32_t timeout = 1000)
31 return ProfilingService::WaitForPacketSent(m_ProfilingService, timeout);
33 armnn::profiling::ProfilingService m_ProfilingService;
36 BOOST_AUTO_TEST_SUITE(FileOnlyProfilingDecoratorTests)
38 std::string UniqueFileName()
40 std::time_t t = std::time(nullptr);
42 std::strftime(mbstr, sizeof(mbstr), "%Y_%m_%d_%H_%M_%S_", std::localtime(&t));
50 BOOST_AUTO_TEST_CASE(TestFileOnlyProfiling)
52 // This test requires the CpuRef backend to be enabled
53 if(!BackendRegistryInstance().IsBackendRegistered("CpuRef"))
58 // Create a temporary file name.
59 boost::filesystem::path tempPath = boost::filesystem::temp_directory_path();
60 boost::filesystem::path tempFile = UniqueFileName();
61 tempPath = tempPath / tempFile;
62 armnn::Runtime::CreationOptions creationOptions;
63 creationOptions.m_ProfilingOptions.m_EnableProfiling = true;
64 creationOptions.m_ProfilingOptions.m_FileOnly = true;
65 creationOptions.m_ProfilingOptions.m_CapturePeriod = 100;
66 creationOptions.m_ProfilingOptions.m_TimelineEnabled = true;
67 ILocalPacketHandlerSharedPtr localPacketHandlerPtr = std::make_shared<TestTimelinePacketHandler>();
68 creationOptions.m_ProfilingOptions.m_LocalPacketHandlers.push_back(localPacketHandlerPtr);
70 armnn::Runtime runtime(creationOptions);
72 // Load a simple network
73 // build up the structure of the network
74 INetworkPtr net(INetwork::Create());
76 IConnectableLayer* input = net->AddInputLayer(0, "input");
78 NormalizationDescriptor descriptor;
79 IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor, "normalization");
81 IConnectableLayer* output = net->AddOutputLayer(0, "output");
83 input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
84 normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
86 input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
87 normalize->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
89 // optimize the network
90 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
91 IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime.GetDeviceSpec());
93 // Load it into the runtime. It should succeed.
94 armnn::NetworkId netId;
95 BOOST_TEST(runtime.LoadNetwork(netId, std::move(optNet)) == Status::Success);
97 static_cast<TestTimelinePacketHandler*>(localPacketHandlerPtr.get())->WaitOnInferenceCompletion(3000);
100 BOOST_AUTO_TEST_CASE(DumpOutgoingValidFileEndToEnd, * boost::unit_test::disabled())
102 // Create a temporary file name.
103 boost::filesystem::path tempPath = boost::filesystem::temp_directory_path();
104 boost::filesystem::path tempFile = UniqueFileName();
105 tempPath = tempPath / tempFile;
106 armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
107 options.m_EnableProfiling = true;
108 options.m_FileOnly = true;
109 options.m_IncomingCaptureFile = "";
110 options.m_OutgoingCaptureFile = tempPath.string();
111 options.m_CapturePeriod = 100;
113 FileOnlyHelperService helper;
115 // Enable the profiling service
116 armnn::profiling::ProfilingService profilingService;
117 profilingService.ResetExternalProfilingOptions(options, true);
118 // Bring the profiling service to the "WaitingForAck" state
119 profilingService.Update();
120 profilingService.Update();
123 BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
125 profilingService.Update();
126 // First packet sent will be the SendStreamMetaDataPacket, it's possible though unlikely that it will be sent twice
127 // The second or possibly third packet will be the CounterDirectoryPacket which means the
128 // ConnectionAcknowledgedCommandHandler has set the state to active
129 uint32_t packetCount = 0;
130 while(profilingService.GetCurrentState() != ProfilingState::Active && packetCount < 3)
132 if(!helper.WaitForPacketsSent())
134 BOOST_FAIL("Timeout waiting for packets");
139 BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
140 // Minimum test here is to check that the file was created.
141 BOOST_CHECK(boost::filesystem::exists(tempPath.c_str()) == true);
143 // Increment a counter.
144 BOOST_CHECK(profilingService.IsCounterRegistered(0) == true);
145 profilingService.IncrementCounterValue(0);
146 BOOST_CHECK(profilingService.GetAbsoluteCounterValue(0) > 0);
147 BOOST_CHECK(profilingService.GetDeltaCounterValue(0) > 0);
149 // At this point the profiling service is active and we've activated all the counters. Waiting a collection
150 // period should be enough to have some data in the file.
152 // Wait for 1 collection period plus a bit of overhead..
153 helper.WaitForPacketsSent();
155 // In order to flush the files we need to gracefully close the profiling service.
156 options.m_EnableProfiling = false;
157 profilingService.ResetExternalProfilingOptions(options, true);
159 // The output file size should be greater than 0.
160 BOOST_CHECK(armnnUtils::Filesystem::GetFileSize(tempPath.string().c_str()) > 0);
162 // Delete the tmp file.
163 BOOST_CHECK(armnnUtils::Filesystem::Remove(tempPath.string().c_str()));
166 BOOST_AUTO_TEST_SUITE_END()