2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // See LICENSE file in the project root for full license information.
6 #include <boost/test/unit_test.hpp>
7 #include <boost/test/output_test_stream.hpp>
8 #include <boost/algorithm/string.hpp>
13 #include <armnn/TypesUtils.hpp>
14 #include <Profiling.hpp>
19 size_t GetProfilerEventSequenceSize(armnn::Profiler* profiler)
23 return static_cast<size_t>(-1);
26 return profiler->m_EventSequence.size();
33 void RegisterUnregisterProfilerSingleThreadImpl()
35 // Important! Regular assertions must be used in this function for testing (rather than
36 // BOOST_TEST macros) otherwise multi-threading tests would randomly fail.
38 // Get a reference to the profiler manager.
39 armnn::ProfilerManager& profilerManager = armnn::ProfilerManager::GetInstance();
41 // Check that there's no profiler registered for this thread.
42 assert(!profilerManager.GetProfiler());
44 // Create and register a profiler for this thread.
45 std::unique_ptr<armnn::Profiler> profiler = std::make_unique<armnn::Profiler>();
46 profilerManager.RegisterProfiler(profiler.get());
48 // Check that on a single thread we get the same profiler we registered.
49 assert(profiler.get() == profilerManager.GetProfiler());
51 // Destroy the profiler.
54 // Check that the profiler has been un-registered for this thread.
55 assert(!profilerManager.GetProfiler());
60 BOOST_AUTO_TEST_SUITE(Profiler)
62 BOOST_AUTO_TEST_CASE(EnableDisableProfiling)
64 std::unique_ptr<armnn::Profiler> profiler = std::make_unique<armnn::Profiler>();
66 // Check that profiling is disabled by default.
67 BOOST_TEST(!profiler->IsProfilingEnabled());
70 profiler->EnableProfiling(true);
72 // Check that profiling is enabled.
73 BOOST_TEST(profiler->IsProfilingEnabled());
76 profiler->EnableProfiling(false);
78 // Check that profiling is disabled.
79 BOOST_TEST(!profiler->IsProfilingEnabled());
82 BOOST_AUTO_TEST_CASE(RegisterUnregisterProfilerSingleThread)
84 RegisterUnregisterProfilerSingleThreadImpl();
87 BOOST_AUTO_TEST_CASE(RegisterUnregisterProfilerMultipleThreads)
89 std::thread thread1([]() { RegisterUnregisterProfilerSingleThreadImpl(); });
90 std::thread thread2([]() { RegisterUnregisterProfilerSingleThreadImpl(); });
91 std::thread thread3([]() { RegisterUnregisterProfilerSingleThreadImpl(); });
98 BOOST_AUTO_TEST_CASE(ProfilingMacros)
100 // Get a reference to the profiler manager.
101 armnn::ProfilerManager& profilerManager = armnn::ProfilerManager::GetInstance();
103 { // --- No profiler ---
105 // Check that there's no profiler registered for this thread.
106 BOOST_TEST(!profilerManager.GetProfiler());
108 // Test scoped event.
109 { ARMNN_SCOPED_PROFILING_EVENT(armnn::Compute::CpuAcc, "test"); }
111 // Check that we still cannot get a profiler for this thread.
112 BOOST_TEST(!profilerManager.GetProfiler());
115 // Create and register a profiler for this thread.
116 std::unique_ptr<armnn::Profiler> profiler = std::make_unique<armnn::Profiler>();
117 profilerManager.RegisterProfiler(profiler.get());
119 { // --- Profiler, but profiling disabled ---
121 // Get current event sequence size.
122 size_t eventSequenceSizeBefore = armnn::GetProfilerEventSequenceSize(profiler.get());
124 // Test scoped macro.
125 { ARMNN_SCOPED_PROFILING_EVENT(armnn::Compute::CpuAcc, "test"); }
127 // Check that no profiling event has been added to the sequence.
128 size_t eventSequenceSizeAfter = armnn::GetProfilerEventSequenceSize(profiler.get());
129 BOOST_TEST(eventSequenceSizeBefore == eventSequenceSizeAfter);
133 profiler->EnableProfiling(true);
135 { // --- Profiler, and profiling enabled ---
137 // Get current event sequence size.
138 size_t eventSequenceSizeBefore = armnn::GetProfilerEventSequenceSize(profiler.get());
140 // Test scoped macro.
141 { ARMNN_SCOPED_PROFILING_EVENT(armnn::Compute::CpuAcc, "test"); }
143 // Check that a profiling event has been added to the sequence.
144 size_t eventSequenceSizeAfter = armnn::GetProfilerEventSequenceSize(profiler.get());
145 BOOST_TEST(eventSequenceSizeAfter == eventSequenceSizeBefore + 1);
148 // Disable profiling here to not print out anything on stdout.
149 profiler->EnableProfiling(false);
152 BOOST_AUTO_TEST_CASE(RuntimeLoadNetwork)
154 // Get a reference to the profiler manager.
155 armnn::ProfilerManager& profilerManager = armnn::ProfilerManager::GetInstance();
157 // Check that there's no profiler registered for this thread.
158 BOOST_TEST(!profilerManager.GetProfiler());
160 // Build a mock-network and load it into the runtime.
161 armnn::IRuntime::CreationOptions options;
162 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
163 armnn::NetworkId networkIdentifier = 1;
164 armnn::INetworkPtr mockNetwork(armnn::INetwork::Create());
165 mockNetwork->AddInputLayer(0, "test layer");
166 std::vector<armnn::Compute> backends = { armnn::Compute::CpuRef };
167 runtime->LoadNetwork(networkIdentifier, armnn::Optimize(*mockNetwork, backends, runtime->GetDeviceSpec()));
169 // Check that now there's a profiler registered for this thread (created and registered by the loading the network).
170 BOOST_TEST(profilerManager.GetProfiler());
172 // Unload the network.
173 runtime->UnloadNetwork(networkIdentifier);
175 // Check that the profiler has been un-registered for this thread.
176 BOOST_TEST(!profilerManager.GetProfiler());
179 BOOST_AUTO_TEST_CASE(WriteEventResults)
181 // Get a reference to the profiler manager.
182 armnn::ProfilerManager& profileManager = armnn::ProfilerManager::GetInstance();
184 // Create and register a profiler for this thread.
185 std::unique_ptr<armnn::Profiler> profiler = std::make_unique<armnn::Profiler>();
186 profileManager.RegisterProfiler(profiler.get());
189 profiler->EnableProfiling(true);
191 { // --- Profiler, and profiling enabled ---
193 // Get current event sequence size.
194 size_t eventSequenceSizeBefore = armnn::GetProfilerEventSequenceSize(profiler.get());
196 // Test scoped macro.
198 // Need to directly create a ScopedProfilingEvent as the one created by the macro falls out of scope
199 // immediately causing the Event.Stop() function method to be called immediately after the Event.Start()
200 // function resulting in periodic test failures on the Dent and Smith HiKeys
201 armnn::ScopedProfilingEvent testEvent(armnn::Compute::CpuAcc, "test", armnn::WallClockTimer());
202 std::this_thread::sleep_for(std::chrono::milliseconds(10));
205 // Check that a profiling event has been added to the sequence.
206 size_t eventSequenceSizeAfter = armnn::GetProfilerEventSequenceSize(profiler.get());
207 BOOST_TEST(eventSequenceSizeAfter == eventSequenceSizeBefore + 1);
209 boost::test_tools::output_test_stream output;
210 profiler->AnalyzeEventsAndWriteResults(output);
211 BOOST_TEST(!output.is_empty(false));
213 // output should contain event name 'test'
214 BOOST_CHECK(boost::contains(output.str(), "test"));
216 // output should contain headers
217 BOOST_CHECK(boost::contains(output.str(), "Event Sequence - Name"));
218 BOOST_CHECK(boost::contains(output.str(), "Event Stats - Name"));
219 BOOST_CHECK(boost::contains(output.str(), "Total"));
220 BOOST_CHECK(boost::contains(output.str(), "Device"));
221 // output should contain compute device 'CpuAcc'
222 BOOST_CHECK(boost::contains(output.str(), "CpuAcc"));
223 // output should not contain un-readable numbers
224 BOOST_CHECK(!(boost::contains(output.str(), "e+")));
225 // output should not contain un-readable numbers
226 BOOST_CHECK(!(boost::contains(output.str(), "+")));
227 // output should not contain zero value
228 BOOST_CHECK(!(boost::contains(output.str(), " 0 ")));
231 // Disable profiling here to not print out anything on stdout.
232 profiler->EnableProfiling(false);
235 BOOST_AUTO_TEST_SUITE_END()