ArmNN
 22.08
FileOnlyProfilingDecoratorTests.cpp File Reference
#include "PrintPacketHeaderHandler.hpp"
#include "ProfilingOptionsConverter.hpp"
#include "ProfilingTestUtils.hpp"
#include <Runtime.hpp>
#include "TestTimelinePacketHandler.hpp"
#include <armnnUtils/Filesystem.hpp>
#include <client/src/ProfilingService.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 40 of file FileOnlyProfilingDecoratorTests.cpp.

References CompareOutput(), IOutputSlot::Connect(), arm::pipe::ConvertExternalProfilingOptions(), RuntimeImpl::EnqueueWorkload(), armnn::error, RuntimeImpl::GetDeviceSpec(), TimelineModel::GetErrors(), IConnectableLayer::GetInputSlot(), RuntimeImpl::GetInputTensorInfo(), arm::pipe::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(), armnn::Rsqrt, TensorInfo::SetConstant(), and IOutputSlot::SetTensorInfo().

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