blob: 1b37b189dd5f932f64d7d889febfbea6e6a0eec0 [file] [log] [blame]
Anthony Barbier06ea0482018-02-22 15:45:35 +00001/*
2 * Copyright (c) 2017-2018 ARM Limited.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#include "SchedulerTimer.h"
25
26#include "WallClockTimer.h"
27#include "arm_compute/core/CPP/ICPPKernel.h"
Jenkinsb3a371b2018-05-23 11:36:53 +010028#include "arm_compute/core/utils/misc/Cast.h"
29#include "arm_compute/graph/INode.h"
Anthony Barbier06ea0482018-02-22 15:45:35 +000030
31namespace arm_compute
32{
33namespace test
34{
35namespace framework
36{
37std::string SchedulerTimer::id() const
38{
39 return "SchedulerTimer";
40}
41
42class Interceptor final : public IScheduler
43{
44public:
45 /** Default constructor. */
46 Interceptor(std::list<SchedulerTimer::kernel_info> &kernels, IScheduler &real_scheduler, ScaleFactor scale_factor)
Jenkinsb3a371b2018-05-23 11:36:53 +010047 : _kernels(kernels), _real_scheduler(real_scheduler), _timer(scale_factor), _prefix()
Anthony Barbier06ea0482018-02-22 15:45:35 +000048 {
49 }
50
51 void set_num_threads(unsigned int num_threads) override
52 {
53 _real_scheduler.set_num_threads(num_threads);
54 }
55
56 unsigned int num_threads() const override
57 {
58 return _real_scheduler.num_threads();
59 }
60
Jenkinsb3a371b2018-05-23 11:36:53 +010061 void set_prefix(std::string prefix)
62 {
63 _prefix = std::move(prefix);
64 }
65
Anthony Barbier06ea0482018-02-22 15:45:35 +000066 void schedule(ICPPKernel *kernel, unsigned int split_dimension) override
67 {
68 _timer.start();
69 _real_scheduler.schedule(kernel, split_dimension);
70 _timer.stop();
71
72 SchedulerTimer::kernel_info info;
73 info.name = kernel->name();
Jenkinsb3a371b2018-05-23 11:36:53 +010074 info.prefix = _prefix;
Anthony Barbier06ea0482018-02-22 15:45:35 +000075 info.measurements = _timer.measurements();
76 _kernels.push_back(std::move(info));
77 }
78
79private:
80 std::list<SchedulerTimer::kernel_info> &_kernels;
81 IScheduler &_real_scheduler;
82 WallClockTimer _timer;
Jenkinsb3a371b2018-05-23 11:36:53 +010083 std::string _prefix;
Anthony Barbier06ea0482018-02-22 15:45:35 +000084};
85
86SchedulerTimer::SchedulerTimer(ScaleFactor scale_factor)
Jenkinsb3a371b2018-05-23 11:36:53 +010087 : _kernels(), _real_scheduler(nullptr), _real_scheduler_type(), _real_graph_function(nullptr), _scale_factor(scale_factor), _interceptor(nullptr)
Anthony Barbier06ea0482018-02-22 15:45:35 +000088{
89}
90
Jenkinsb3a371b2018-05-23 11:36:53 +010091void SchedulerTimer::test_start()
Anthony Barbier06ea0482018-02-22 15:45:35 +000092{
Jenkinsb3a371b2018-05-23 11:36:53 +010093 // Start intercepting tasks:
94 ARM_COMPUTE_ERROR_ON(_real_graph_function != nullptr);
95 _real_graph_function = graph::TaskExecutor::get().execute_function;
96 auto task_interceptor = [this](graph::ExecutionTask & task)
97 {
98 Interceptor *scheduler = nullptr;
99 if(dynamic_cast<Interceptor *>(this->_interceptor.get()) != nullptr)
100 {
101 scheduler = arm_compute::utils::cast::polymorphic_downcast<Interceptor *>(_interceptor.get());
102 if(task.node != nullptr && !task.node->name().empty())
103 {
104 scheduler->set_prefix(task.node->name() + "/");
105 }
106 else
107 {
108 scheduler->set_prefix("");
109 }
110 }
111
112 this->_real_graph_function(task);
113
114 if(scheduler != nullptr)
115 {
116 scheduler->set_prefix("");
117 }
118 };
119
Anthony Barbier06ea0482018-02-22 15:45:35 +0000120 ARM_COMPUTE_ERROR_ON(_real_scheduler != nullptr);
121 _real_scheduler_type = Scheduler::get_type();
122 //Note: We can't currently replace a custom scheduler
123 if(_real_scheduler_type != Scheduler::Type::CUSTOM)
124 {
Jenkinsb3a371b2018-05-23 11:36:53 +0100125 _real_scheduler = &Scheduler::get();
126 _interceptor = std::make_shared<Interceptor>(_kernels, *_real_scheduler, _scale_factor);
127 Scheduler::set(std::static_pointer_cast<IScheduler>(_interceptor));
128 graph::TaskExecutor::get().execute_function = task_interceptor;
Anthony Barbier06ea0482018-02-22 15:45:35 +0000129 }
Jenkinsb3a371b2018-05-23 11:36:53 +0100130}
131
132void SchedulerTimer::start()
133{
Anthony Barbier06ea0482018-02-22 15:45:35 +0000134 _kernels.clear();
135}
136
Jenkinsb3a371b2018-05-23 11:36:53 +0100137void SchedulerTimer::test_stop()
Anthony Barbier06ea0482018-02-22 15:45:35 +0000138{
139 // Restore real scheduler
140 Scheduler::set(_real_scheduler_type);
Jenkinsb3a371b2018-05-23 11:36:53 +0100141 _real_scheduler = nullptr;
142 _interceptor = nullptr;
143 graph::TaskExecutor::get().execute_function = _real_graph_function;
144 _real_graph_function = nullptr;
Anthony Barbier06ea0482018-02-22 15:45:35 +0000145}
146
147Instrument::MeasurementsMap SchedulerTimer::measurements() const
148{
149 MeasurementsMap measurements;
150 unsigned int kernel_number = 0;
151 for(auto kernel : _kernels)
152 {
Jenkinsb3a371b2018-05-23 11:36:53 +0100153 measurements.emplace(kernel.prefix + kernel.name + " #" + support::cpp11::to_string(kernel_number++), kernel.measurements.begin()->second);
Anthony Barbier06ea0482018-02-22 15:45:35 +0000154 }
155
156 return measurements;
157}
158} // namespace framework
159} // namespace test
160} // namespace arm_compute