1d591ae3c7ea01ae8cfacb570e931a9bdbda4d28
[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 for unavailable backends
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   assert(fallback != nullptr); // There must be at least one fallback
54
55   // 1. Backend for All operations
56   const backend::Backend *backend_all = resolveBackend(manual_options.backend_for_all, fallback);
57   VERBOSE(ManualScheduler) << "Default backend for all ops: " << backend_all->config()->id()
58                            << std::endl;
59
60   graph.operations().iterate([&](const ir::OperationIndex &index, const ir::Operation &) {
61     backend_resolver->setBackend(index, backend_all);
62   });
63
64   // 2. Backend per operation type
65   std::unordered_map<ir::OpCode, backend::Backend *> op_type_map;
66   for (auto &pair : manual_options.opcode_to_backend)
67   {
68     op_type_map.emplace(pair.first, BackendManager::get().get(pair.second));
69   }
70   // By default, Custom uses cpu backend
71   op_type_map[ir::OpCode::Custom] = BackendManager::get().get("cpu");
72
73   graph.operations().iterate([&](const ir::OperationIndex &index, const ir::Operation &operation) {
74     auto itr = op_type_map.find(operation.opcode());
75     if (itr != op_type_map.end())
76     {
77       backend_resolver->setBackend(index, itr->second);
78     }
79   });
80
81   // 3. Backend per operation
82   for (auto &pair : manual_options.index_to_backend)
83   {
84     const auto &key = pair.first;
85     const auto &val = pair.second;
86
87     try
88     {
89       graph.operations().at(key); // Check if exist, or this will throw
90       backend_resolver->setBackend(
91           key, BackendManager::get().get(
92                    val)); // TODO Ensure this backend is available in backend contexts
93     }
94     catch (...)
95     {
96       VERBOSE(ManualScheduler) << "Invalid value while OperationIndex to Backend mapping : @"
97                                << key.value() << " -> \"" << val << "\"" << std::endl;
98     }
99   }
100
101   // Dump final assignment
102   backend_resolver->iterate([&](const ir::OperationIndex &index, const backend::Backend &backend) {
103     VERBOSE(ManualScheduler) << "backend for operation #" << index.value() << ": "
104                              << backend.config()->id() << std::endl;
105   });
106
107   return backend_resolver;
108 }
109
110 const backend::Backend *ManualScheduler::resolveBackend(const std::string &id,
111                                                         const backend::Backend *fallback)
112 {
113   // Ensure if the backend is available in the backend
114   const backend::Backend *backend = BackendManager::get().get(id);
115   if (!backend || _backend_contexts.find(backend) == _backend_contexts.end())
116   {
117     backend = fallback;
118   }
119   return backend;
120 }
121
122 } // namespace compiler
123 } // namespace onert