066b52ee162c3d5ce683583fac78ddc08ac19f54
[platform/core/ml/nnfw.git] / runtime / onert / core / src / exec / ExecutionObservers.cc
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "exec/ExecutionObservers.h"
18
19 #include <string>
20
21 #include "util/logging.h"
22 #include "exec/IExecutor.h"
23 #include "misc/polymorphic_downcast.h"
24 #include "ir/OpSequence.h"
25 #include "util/EventWriter.h"
26
27 namespace onert
28 {
29
30 namespace exec
31 {
32
33 void ProfileObserver::handleBegin(onert::exec::IExecutor *, const ir::OpSequence *,
34                                   const onert::backend::Backend *backend)
35 {
36   _timer = backend->config()->timer();
37   if (_timer == nullptr)
38     throw std::runtime_error("To profile backend timer() method must be implemented");
39   _timer->handleBegin();
40 }
41
42 void ProfileObserver::handleEnd(IExecutor *exec, const ir::OpSequence *op_seq,
43                                 const backend::Backend *backend)
44 {
45   _timer->handleEnd();
46   const auto timer_res = _timer->getTime();
47
48   // NOTE This assumes there is just one operation in a op_seq
49   const auto &node = _graph.operations().at(op_seq->operations().at(0));
50   auto node_name = node.name();
51   VERBOSE(ProfileInfo) << "Time for " << node_name << " : " << timer_res << std::endl;
52
53   // fill ExecTime:
54   bool is_quantized = exec->graph().operands().at(node.getInputs().at(0)).typeInfo().type() ==
55                       ir::DataType::QUANT_UINT8_ASYMM;
56
57   uint32_t size = 0;
58   for (const auto &ind : (node.getInputs() + node.getOutputs()) | ir::Remove::UNDEFINED)
59   {
60     size += exec->graph().operands().at(ind).info().total_size();
61   }
62   if (node_name == "Permute")
63   {
64     // TODO Change it to updateOperationExecTime()
65     _et->updatePermuteTime(backend, backend, is_quantized, size, timer_res);
66   }
67   else
68   {
69     _et->updateOperationExecTime(backend, node_name, is_quantized, size, timer_res);
70   }
71 };
72
73 ChromeTracingObserver::ChromeTracingObserver(const std::string &filepath, const ir::Graph &graph)
74     : _base_filepath(filepath), _recorder{}, _collector{&_recorder}, _graph{graph}
75 {
76 }
77
78 ChromeTracingObserver::~ChromeTracingObserver()
79 {
80   try
81   {
82     EventWriter{_recorder}.writeToFiles(_base_filepath);
83   }
84   catch (const std::exception &e)
85   {
86     std::cerr << "E: Fail to record event in ChromeTracingObserver: " << e.what() << std::endl;
87   }
88 }
89
90 void ChromeTracingObserver::handleBegin(IExecutor *)
91 {
92   _collector.onEvent(EventCollector::Event{EventCollector::Edge::BEGIN, "runtime", "Graph"});
93 }
94
95 void ChromeTracingObserver::handleBegin(IExecutor *, const ir::OpSequence *op_seq,
96                                         const backend::Backend *backend)
97 {
98   std::string backend_id = backend->config()->id();
99   _collector.onEvent(EventCollector::Event{EventCollector::Edge::BEGIN, backend_id,
100                                            opSequenceTag(op_seq, _graph.operations())});
101 }
102
103 void ChromeTracingObserver::handleEnd(IExecutor *, const ir::OpSequence *op_seq,
104                                       const backend::Backend *backend)
105 {
106   std::string backend_id = backend->config()->id();
107   _collector.onEvent(EventCollector::Event{EventCollector::Edge::END, backend_id,
108                                            opSequenceTag(op_seq, _graph.operations())});
109 }
110
111 void ChromeTracingObserver::handleEnd(IExecutor *)
112 {
113   _collector.onEvent(EventCollector::Event{EventCollector::Edge::END, "runtime", "Graph"});
114 }
115
116 std::string ChromeTracingObserver::opSequenceTag(const ir::OpSequence *op_seq,
117                                                  const ir::Operations &operations)
118 {
119   if (op_seq->size() == 0)
120     return "Empty OpSequence";
121
122   const auto &first_op_idx = op_seq->operations().at(0);
123   const auto &first_op_node = operations.at(first_op_idx);
124   std::string tag = "$" + std::to_string(first_op_idx.value());
125   tag += " " + first_op_node.name();
126   if (op_seq->size() > 1)
127   {
128     tag += " (+" + std::to_string(op_seq->size() - 1) + ")";
129   }
130   return tag;
131 }
132
133 } // namespace exec
134
135 } // namespace onert