Imported Upstream version 1.12.0
[platform/core/ml/nnfw.git] / runtime / onert / core / src / compiler / ManualScheduler.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 "ManualScheduler.h"
18 #include "ir/OpCode.h"
19 #include "ir/Operations.Include.h"
20 #include "backend/Backend.h"
21 #include "backend/IConfig.h"
22 #include "compiler/BackendManager.h"
23 #include "util/ConfigSource.h"
24 #include "util/logging.h"
25 #include "misc/string_helpers.h"
26
27 namespace onert
28 {
29 namespace compiler
30 {
31
32 ManualScheduler::ManualScheduler(const backend::BackendContexts &backend_contexts,
33                                  const compiler::CompilerOptions &options)
34     : _backend_contexts{backend_contexts}, _options{options}
35 {
36 }
37
38 std::unique_ptr<BackendResolver> ManualScheduler::schedule(const ir::Graph &graph)
39 {
40   const auto &manual_options = _options.manual_scheduler_options;
41   auto backend_resolver = std::make_unique<compiler::BackendResolver>();
42
43   // This fallback will be used in case that `backend_for_all` is unavailable
44   auto fallback = [&]() -> const backend::Backend * {
45     for (auto backend_id : _options.backend_list)
46     {
47       auto backend = resolveBackend(backend_id);
48       if (backend)
49         return backend;
50     }
51     return nullptr;
52   }();
53   if (fallback == nullptr)
54     throw std::runtime_error{"No loaded backends available."};
55
56   // 1. Backend for All operations
57   const backend::Backend *backend_all = resolveBackend(manual_options.backend_for_all, fallback);
58   VERBOSE(ManualScheduler) << "Default backend for all ops: " << backend_all->config()->id()
59                            << std::endl;
60
61   graph.operations().iterate([&](const ir::OperationIndex &index, const ir::Operation &) {
62     backend_resolver->setBackend(index, backend_all);
63   });
64
65   // 2. Backend per operation type
66   std::unordered_map<ir::OpCode, backend::Backend *> op_type_map;
67   for (auto &pair : manual_options.opcode_to_backend)
68   {
69     op_type_map.emplace(pair.first, BackendManager::get().get(pair.second));
70   }
71   // By default, Custom uses cpu backend
72   op_type_map[ir::OpCode::Custom] = BackendManager::get().get("cpu");
73
74   graph.operations().iterate([&](const ir::OperationIndex &index, const ir::Operation &operation) {
75     auto itr = op_type_map.find(operation.opcode());
76     if (itr != op_type_map.end())
77     {
78       backend_resolver->setBackend(index, itr->second);
79     }
80   });
81
82   // 3. Backend per operation
83   for (auto &pair : manual_options.index_to_backend)
84   {
85     const auto &key = pair.first;
86     const auto &val = pair.second;
87
88     try
89     {
90       graph.operations().at(key); // Check if exist, or this will throw
91       backend_resolver->setBackend(
92           key, BackendManager::get().get(
93                    val)); // TODO Ensure this backend is available in backend contexts
94     }
95     catch (...)
96     {
97       VERBOSE(ManualScheduler) << "Invalid value while OperationIndex to Backend mapping : @"
98                                << key.value() << " -> \"" << val << "\"" << std::endl;
99     }
100   }
101
102   // Dump final assignment
103   WHEN_LOG_ENABLED(backend_resolver->iterate(
104       [&](const ir::OperationIndex &index, const backend::Backend &backend) {
105         VERBOSE(ManualScheduler) << "backend for operation #" << index.value() << ": "
106                                  << backend.config()->id() << std::endl;
107       }));
108
109   return backend_resolver;
110 }
111
112 const backend::Backend *ManualScheduler::resolveBackend(const std::string &id,
113                                                         const backend::Backend *fallback)
114 {
115   // Ensure if the backend is available in the current backend context
116   const backend::Backend *backend = BackendManager::get().get(id);
117   if (!backend || _backend_contexts.find(backend) == _backend_contexts.end())
118   {
119     backend = fallback;
120   }
121   return backend;
122 }
123
124 } // namespace compiler
125 } // namespace onert