ArmNN
 21.11
FileOnlyProfilingDecoratorTests.cpp File Reference
#include <armnnUtils/Filesystem.hpp>
#include <ProfilingService.hpp>
#include "ProfilingTestUtils.hpp"
#include "PrintPacketHeaderHandler.hpp"
#include <Runtime.hpp>
#include "TestTimelinePacketHandler.hpp"
#include <doctest/doctest.h>
#include <common/include/LabelsAndEventClasses.hpp>
#include <cstdio>
#include <sstream>
#include <sys/stat.h>

Go to the source code of this file.

Functions

 TEST_SUITE ("FileOnlyProfilingDecoratorTests")
 

Function Documentation

◆ TEST_SUITE()

TEST_SUITE ( "FileOnlyProfilingDecoratorTests"  )

Definition at line 37 of file FileOnlyProfilingDecoratorTests.cpp.

References CompareOutput(), IOutputSlot::Connect(), INetwork::Create(), RuntimeImpl::EnqueueWorkload(), armnn::error, armnn::Float32, RuntimeImpl::GetDeviceSpec(), TimelineModel::GetErrors(), IConnectableLayer::GetInputSlot(), RuntimeImpl::GetInputTensorInfo(), armnn::profiling::GetModelDescription(), IConnectableLayer::GetOutputSlot(), RuntimeImpl::GetOutputTensorInfo(), armnn::GetProfilingService(), GetSuitableBackendRegistered(), RuntimeImpl::LoadNetwork(), IRuntime::CreationOptions::ExternalProfilingOptions::m_CapturePeriod, IRuntime::CreationOptions::ExternalProfilingOptions::m_EnableProfiling, IRuntime::CreationOptions::ExternalProfilingOptions::m_FileOnly, IRuntime::CreationOptions::ExternalProfilingOptions::m_IncomingCaptureFile, IRuntime::CreationOptions::ExternalProfilingOptions::m_LocalPacketHandlers, IRuntime::CreationOptions::ExternalProfilingOptions::m_OutgoingCaptureFile, IRuntime::CreationOptions::m_ProfilingOptions, IRuntime::CreationOptions::ExternalProfilingOptions::m_TimelineEnabled, armnnUtils::Filesystem::NamedTempFile(), armnn::Optimize(), ProfilingService::ResetExternalProfilingOptions(), ProfilingService::ResetGuidGenerator(), armnn::Rsqrt, TensorInfo::SetConstant(), IOutputSlot::SetTensorInfo(), and armnn::Success.

38 {
39 TEST_CASE("TestFileOnlyProfiling")
40 {
41  // Get all registered backends
42  std::vector<BackendId> suitableBackends = GetSuitableBackendRegistered();
43 
44  // Run test for each backend separately
45  for (auto const& backend : suitableBackends)
46  {
47  // Enable m_FileOnly but also provide ILocalPacketHandler which should consume the packets.
48  // This won't dump anything to file.
49  armnn::IRuntime::CreationOptions creationOptions;
50  creationOptions.m_ProfilingOptions.m_EnableProfiling = true;
51  creationOptions.m_ProfilingOptions.m_FileOnly = true;
52  creationOptions.m_ProfilingOptions.m_CapturePeriod = 100;
53  creationOptions.m_ProfilingOptions.m_TimelineEnabled = true;
54  ILocalPacketHandlerSharedPtr localPacketHandlerPtr = std::make_shared<TestTimelinePacketHandler>();
55  creationOptions.m_ProfilingOptions.m_LocalPacketHandlers.push_back(localPacketHandlerPtr);
56 
57  armnn::RuntimeImpl runtime(creationOptions);
58  // ensure the GUID generator is reset to zero
60 
61  // Load a simple network
62  // build up the structure of the network
63  INetworkPtr net(INetwork::Create());
64 
65  IConnectableLayer* input = net->AddInputLayer(0, "input");
66 
67  ElementwiseUnaryDescriptor descriptor(UnaryOperation::Rsqrt);
68  IConnectableLayer* Rsqrt = net->AddElementwiseUnaryLayer(descriptor, "Rsqrt");
69 
70  IConnectableLayer* output = net->AddOutputLayer(0, "output");
71 
72  input->GetOutputSlot(0).Connect(Rsqrt->GetInputSlot(0));
73  Rsqrt->GetOutputSlot(0).Connect(output->GetInputSlot(0));
74 
75  input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
76  Rsqrt->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
77 
78  std::vector<armnn::BackendId> backendsVec {backend};
79  IOptimizedNetworkPtr optNet = Optimize(*net, backendsVec, runtime.GetDeviceSpec());
80 
81  // Load it into the runtime. It should succeed.
82  armnn::NetworkId netId;
83  CHECK(runtime.LoadNetwork(netId, std::move(optNet)) == Status::Success);
84 
85  // Creates structures for input & output.
86  std::vector<float> inputData(16);
87  std::vector<float> outputData(16);
88  for (unsigned int i = 0; i < 16; ++i) {
89  inputData[i] = 9.0;
90  outputData[i] = 3.0;
91  }
92 
93  TensorInfo inputTensorInfo = runtime.GetInputTensorInfo(netId, 0);
94  inputTensorInfo.SetConstant(true);
95  InputTensors inputTensors
96  {
97  {0, ConstTensor(inputTensorInfo, inputData.data())}
98  };
99  OutputTensors outputTensors
100  {
101  {0, Tensor(runtime.GetOutputTensorInfo(netId, 0), outputData.data())}
102  };
103 
104  // Does the inference.
105  runtime.EnqueueWorkload(netId, inputTensors, outputTensors);
106 
107  static_cast<TestTimelinePacketHandler *>(localPacketHandlerPtr.get())->WaitOnInferenceCompletion(3000);
108 
109  const TimelineModel &model =
110  static_cast<TestTimelinePacketHandler *>(localPacketHandlerPtr.get())->GetTimelineModel();
111 
112  for (auto &error : model.GetErrors()) {
113  std::cout << error.what() << std::endl;
114  }
115  CHECK(model.GetErrors().empty());
116  std::vector<std::string> desc = GetModelDescription(model);
117  std::vector<std::string> expectedOutput;
118  expectedOutput.push_back("Entity [0] name = input type = layer");
119  expectedOutput.push_back(" connection [17] from entity [0] to entity [1]");
120  expectedOutput.push_back(" child: Entity [26] backendId = " + backend.Get() + " type = workload");
121  expectedOutput.push_back("Entity [1] name = Rsqrt type = layer");
122  expectedOutput.push_back(" connection [25] from entity [1] to entity [2]");
123  expectedOutput.push_back(" child: Entity [18] backendId = " + backend.Get() + " type = workload");
124  expectedOutput.push_back("Entity [2] name = output type = layer");
125  expectedOutput.push_back(" child: Entity [30] backendId = " + backend.Get() + " type = workload");
126  expectedOutput.push_back("Entity [6] processId = [processId] type = network");
127  expectedOutput.push_back(" child: Entity [0] name = input type = layer");
128  expectedOutput.push_back(" child: Entity [1] name = Rsqrt type = layer");
129  expectedOutput.push_back(" child: Entity [2] name = output type = layer");
130  expectedOutput.push_back(" execution: Entity [34] type = inference");
131  expectedOutput.push_back(" event: [8] class [start_of_life]");
132  expectedOutput.push_back("Entity [18] backendId = " + backend.Get() + " type = workload");
133  expectedOutput.push_back(" execution: Entity [47] type = workload_execution");
134  expectedOutput.push_back("Entity [26] backendId = " + backend.Get() + " type = workload");
135  expectedOutput.push_back(" execution: Entity [39] type = workload_execution");
136  expectedOutput.push_back("Entity [30] backendId = " + backend.Get() + " type = workload");
137  expectedOutput.push_back(" execution: Entity [55] type = workload_execution");
138  expectedOutput.push_back("Entity [34] type = inference");
139  expectedOutput.push_back(" child: Entity [39] type = workload_execution");
140  expectedOutput.push_back(" child: Entity [47] type = workload_execution");
141  expectedOutput.push_back(" child: Entity [55] type = workload_execution");
142  expectedOutput.push_back(" event: [37] class [start_of_life]");
143  expectedOutput.push_back(" event: [63] class [end_of_life]");
144  expectedOutput.push_back("Entity [39] type = workload_execution");
145  expectedOutput.push_back(" event: [43] class [start_of_life]");
146  expectedOutput.push_back(" event: [45] class [end_of_life]");
147  expectedOutput.push_back("Entity [47] type = workload_execution");
148  expectedOutput.push_back(" event: [51] class [start_of_life]");
149  expectedOutput.push_back(" event: [53] class [end_of_life]");
150  expectedOutput.push_back("Entity [55] type = workload_execution");
151  expectedOutput.push_back(" event: [59] class [start_of_life]");
152  expectedOutput.push_back(" event: [61] class [end_of_life]");
153  CHECK(CompareOutput(desc, expectedOutput));
154  }
155 }
156 
157 TEST_CASE("DumpOutgoingValidFileEndToEnd")
158 {
159  // Get all registered backends
160  std::vector<BackendId> suitableBackends = GetSuitableBackendRegistered();
161 
162  // Run test for each backend separately
163  for (auto const& backend : suitableBackends)
164  {
165  // Create a temporary file name.
166  fs::path tempPath = armnnUtils::Filesystem::NamedTempFile("DumpOutgoingValidFileEndToEnd_CaptureFile.txt");
167  // Make sure the file does not exist at this point
168  CHECK(!fs::exists(tempPath));
169 
171  options.m_ProfilingOptions.m_EnableProfiling = true;
172  options.m_ProfilingOptions.m_FileOnly = true;
174  options.m_ProfilingOptions.m_OutgoingCaptureFile = tempPath.string();
175  options.m_ProfilingOptions.m_CapturePeriod = 100;
176  options.m_ProfilingOptions.m_TimelineEnabled = true;
177 
178  ILocalPacketHandlerSharedPtr localPacketHandlerPtr = std::make_shared<TestTimelinePacketHandler>();
179  options.m_ProfilingOptions.m_LocalPacketHandlers.push_back(localPacketHandlerPtr);
180 
181  armnn::RuntimeImpl runtime(options);
182  // ensure the GUID generator is reset to zero
184 
185  // Load a simple network
186  // build up the structure of the network
187  INetworkPtr net(INetwork::Create());
188 
189  IConnectableLayer* input = net->AddInputLayer(0, "input");
190 
191  ElementwiseUnaryDescriptor descriptor(UnaryOperation::Rsqrt);
192  IConnectableLayer* Rsqrt = net->AddElementwiseUnaryLayer(descriptor, "Rsqrt");
193 
194  IConnectableLayer* output = net->AddOutputLayer(0, "output");
195 
196  input->GetOutputSlot(0).Connect(Rsqrt->GetInputSlot(0));
197  Rsqrt->GetOutputSlot(0).Connect(output->GetInputSlot(0));
198 
199  input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
200  Rsqrt->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
201 
202 
203  std::vector<BackendId> backendsVec{backend};
204  IOptimizedNetworkPtr optNet = Optimize(*net, backendsVec, runtime.GetDeviceSpec());
205 
206  // Load it into the runtime. It should succeed.
207  armnn::NetworkId netId;
208  CHECK(runtime.LoadNetwork(netId, std::move(optNet)) == Status::Success);
209 
210  // Creates structures for input & output.
211  std::vector<float> inputData(16);
212  std::vector<float> outputData(16);
213  for (unsigned int i = 0; i < 16; ++i) {
214  inputData[i] = 9.0;
215  outputData[i] = 3.0;
216  }
217 
218  TensorInfo inputTensorInfo = runtime.GetInputTensorInfo(netId, 0);
219  inputTensorInfo.SetConstant(true);
220  InputTensors inputTensors
221  {
222  {0, ConstTensor(inputTensorInfo, inputData.data())}
223  };
224  OutputTensors outputTensors
225  {
226  {0, Tensor(runtime.GetOutputTensorInfo(netId, 0), outputData.data())}
227  };
228 
229  // Does the inference.
230  runtime.EnqueueWorkload(netId, inputTensors, outputTensors);
231 
232  static_cast<TestTimelinePacketHandler *>(localPacketHandlerPtr.get())->WaitOnInferenceCompletion(3000);
233 
234  // In order to flush the files we need to gracefully close the profiling service.
235  options.m_ProfilingOptions.m_EnableProfiling = false;
237 
238  // The output file size should be greater than 0.
239  CHECK(fs::file_size(tempPath) > 0);
240 
241  // NOTE: would be an interesting exercise to take this file and decode it
242 
243  // Delete the tmp file.
244  CHECK(fs::remove(tempPath));
245  }
246 }
247 
248 }
profiling::ProfilingService & GetProfilingService(armnn::RuntimeImpl *runtime)
Definition: TestUtils.cpp:57
std::shared_ptr< ILocalPacketHandler > ILocalPacketHandlerSharedPtr
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:61
std::string m_OutgoingCaptureFile
Path to a file in which outgoing timeline profiling messages will be stored.
Definition: IRuntime.hpp:173
std::vector< std::pair< LayerBindingId, class ConstTensor > > InputTensors
Definition: Tensor.hpp:392
const std::vector< arm::pipe::ProfilingException > & GetErrors() const
std::vector< BackendId > GetSuitableBackendRegistered()
Returns a vector of CpuRef, CpuAcc or GpuAcc backends if they where registered.
std::string m_IncomingCaptureFile
Path to a file in which incoming timeline profiling messages will be stored.
Definition: IRuntime.hpp:175
bool m_EnableProfiling
Indicates whether external profiling is enabled or not.
Definition: IRuntime.hpp:169
bool m_FileOnly
Enable profiling output to file only.
Definition: IRuntime.hpp:177
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
A tensor defined by a TensorInfo (shape and data type) and a mutable backing store.
Definition: Tensor.hpp:319
std::vector< armnn::profiling::ILocalPacketHandlerSharedPtr > m_LocalPacketHandlers
Definition: IRuntime.hpp:182
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:1605
bool CompareOutput(std::vector< std::string > output, std::vector< std::string > expectedOutput)
int NetworkId
Definition: IRuntime.hpp:25
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:327
std::vector< std::pair< LayerBindingId, class Tensor > > OutputTensors
Definition: Tensor.hpp:393
std::unique_ptr< IOptimizedNetwork, void(*)(IOptimizedNetwork *network)> IOptimizedNetworkPtr
Definition: INetwork.hpp:198
void ResetExternalProfilingOptions(const ExternalProfilingOptions &options, bool resetProfilingService=false)
A ElementwiseUnaryDescriptor for the ElementwiseUnaryLayer.
Definition: Descriptors.hpp:98
std::vector< std::string > GetModelDescription(const TimelineModel &model)
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
void SetConstant(const bool IsConstant=true)
Marks the data corresponding to this tensor info as constant.
Definition: Tensor.cpp:516
uint32_t m_CapturePeriod
The duration at which captured profiling messages will be flushed.
Definition: IRuntime.hpp:179
bool m_TimelineEnabled
Indicates whether external timeline profiling is enabled or not.
Definition: IRuntime.hpp:171
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
fs::path NamedTempFile(const char *fileName)
Returns a path to a file in the system temporary folder. If the file existed it will be deleted...
Definition: Filesystem.cpp:23
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:197
virtual int Connect(IInputSlot &destination)=0
ExternalProfilingOptions m_ProfilingOptions
Definition: IRuntime.hpp:184