2 * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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"
32 ManualScheduler::ManualScheduler(const backend::BackendContexts &backend_contexts,
33 const compiler::CompilerOptions &options)
34 : _backend_contexts{backend_contexts}, _options{options}
38 std::unique_ptr<BackendResolver> ManualScheduler::schedule(const ir::Graph &graph)
40 const auto &manual_options = _options.manual_scheduler_options;
41 auto backend_resolver = std::make_unique<compiler::BackendResolver>();
43 // This fallback will be used for unavailable backends
44 auto fallback = [&]() -> const backend::Backend * {
45 for (auto backend_id : _options.backend_list)
47 auto backend = resolveBackend(backend_id);
53 assert(fallback != nullptr); // There must be at least one fallback
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()
60 graph.operations().iterate([&](const ir::OperationIndex &index, const ir::Operation &) {
61 backend_resolver->setBackend(index, backend_all);
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)
68 op_type_map.emplace(pair.first, BackendManager::get().get(pair.second));
70 // By default, Custom uses cpu backend
71 op_type_map[ir::OpCode::Custom] = BackendManager::get().get("cpu");
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())
77 backend_resolver->setBackend(index, itr->second);
81 // 3. Backend per operation
82 for (auto &pair : manual_options.index_to_backend)
84 const auto &key = pair.first;
85 const auto &val = pair.second;
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
96 VERBOSE(ManualScheduler) << "Invalid value while OperationIndex to Backend mapping : @"
97 << key.value() << " -> \"" << val << "\"" << std::endl;
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;
107 return backend_resolver;
110 const backend::Backend *ManualScheduler::resolveBackend(const std::string &id,
111 const backend::Backend *fallback)
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())
122 } // namespace compiler