9d3b19512bb7f9a5777b86ba472004af7beb5d96
[platform/core/ml/nnfw.git] / runtime / neurun / 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 "model/operation/Permute.h"
23 #include "exec/IExecutor.h"
24 #include "misc/polymorphic_downcast.h"
25 #include "model/Subgraph.h"
26
27 namespace neurun
28 {
29
30 namespace exec
31 {
32
33 void ProfileObserver::handleBegin(neurun::exec::IExecutor *, const neurun::model::Subgraph *,
34                                   const neurun::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 model::Subgraph *subgraph,
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 subgraph
49   auto node = subgraph->operations().at(0).node;
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                       model::DataType::QUANT8_ASYMM;
56
57   uint32_t size = 0;
58   for (const auto &input : node->getInputs())
59   {
60     size += exec->graph().operands().at(input).info().total_size();
61   }
62   for (const auto &output : node->getOutputs())
63   {
64     size += exec->graph().operands().at(output).info().total_size();
65   }
66   if (node_name == "Permute")
67   {
68     auto *permute_node = nnfw::misc::polymorphic_downcast<const model::operation::Permute *>(node);
69     assert(permute_node != nullptr);
70     _et->updatePermuteTime(permute_node->param().input_backend_ctx->backend,
71                            permute_node->param().output_backend_ctx->backend, is_quantized, size,
72                            timer_res);
73   }
74   else
75   {
76     _et->updateOperationExecTime(backend, node_name, is_quantized, size, timer_res);
77   }
78 };
79
80 ChromeTracingObserver::ChromeTracingObserver(const std::string &filepath)
81     : _ofs{filepath, std::ofstream::out}, _recorder{}, _collector{&_recorder}
82 {
83 }
84
85 ChromeTracingObserver::~ChromeTracingObserver() { _recorder.writeToFile(_ofs); }
86
87 void ChromeTracingObserver::handleBegin(IExecutor *)
88 {
89   _collector.onEvent(EventCollector::Event{EventCollector::Edge::BEGIN, "runtime", "Graph"});
90 }
91
92 void ChromeTracingObserver::handleBegin(IExecutor *, const model::Subgraph *subgraph,
93                                         const backend::Backend *backend)
94 {
95   std::string backend_id = backend->config()->id();
96   _collector.onEvent(
97       EventCollector::Event{EventCollector::Edge::BEGIN, backend_id, subgraphTag(subgraph)});
98 }
99
100 void ChromeTracingObserver::handleEnd(IExecutor *, const model::Subgraph *subgraph,
101                                       const backend::Backend *backend)
102 {
103   std::string backend_id = backend->config()->id();
104   _collector.onEvent(
105       EventCollector::Event{EventCollector::Edge::END, backend_id, subgraphTag(subgraph)});
106 }
107
108 void ChromeTracingObserver::handleEnd(IExecutor *)
109 {
110   _collector.onEvent(EventCollector::Event{EventCollector::Edge::END, "runtime", "Graph"});
111 }
112
113 std::string ChromeTracingObserver::subgraphTag(const model::Subgraph *subgraph)
114 {
115   if (subgraph->size() == 0)
116     return "Empty Subgraph";
117
118   auto first_op = subgraph->operations().at(0);
119   std::string tag = "$" + std::to_string(first_op.index.value());
120   tag += " " + first_op.node->name();
121   if (subgraph->size() > 1)
122   {
123     tag += " (+" + std::to_string(subgraph->size() - 1) + ")";
124   }
125   return tag;
126 }
127
128 } // namespace exec
129
130 } // namespace neurun