1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
5 // Copyright (C) 2018-2019 Intel Corporation
9 #include <iostream> // cerr
10 #include <functional> // hash
11 #include <numeric> // accumulate
13 #include <ade/util/algorithm.hpp>
16 #include "opencv2/gapi/gkernel.hpp"
18 #include "api/gbackend_priv.hpp"
20 // GKernelPackage public implementation ////////////////////////////////////////
21 void cv::gapi::GKernelPackage::remove(const cv::gapi::GBackend& backend)
23 m_backend_kernels.erase(backend);
26 bool cv::gapi::GKernelPackage::includesAPI(const std::string &id) const
28 // In current form not very efficient (n * log n)
29 auto it = std::find_if(m_backend_kernels.begin(),
30 m_backend_kernels.end(),
31 [&id](const M::value_type &p) {
32 return ade::util::contains(p.second, id);
34 return (it != m_backend_kernels.end());
37 void cv::gapi::GKernelPackage::removeAPI(const std::string &id)
39 for (auto &bk : m_backend_kernels)
43 std::size_t cv::gapi::GKernelPackage::size() const
45 return std::accumulate(m_backend_kernels.begin(),
46 m_backend_kernels.end(),
47 static_cast<std::size_t>(0u),
48 [](std::size_t acc, const M::value_type& v) {
49 return acc + v.second.size();
53 cv::gapi::GKernelPackage cv::gapi::combine(const GKernelPackage &lhs,
54 const GKernelPackage &rhs,
55 const cv::unite_policy policy)
58 if (policy == cv::unite_policy::REPLACE)
60 // REPLACE policy: if there is a collision, prefer RHS
62 // since RHS package has a precedense, start with its copy
63 GKernelPackage result(rhs);
64 // now iterate over LHS package and put kernel if and only
65 // if there's no such one
66 for (const auto &backend : lhs.m_backend_kernels)
68 for (const auto &kimpl : backend.second)
70 if (!result.includesAPI(kimpl.first))
71 result.m_backend_kernels[backend.first].insert(kimpl);
76 else if (policy == cv::unite_policy::KEEP)
78 // KEEP policy: if there is a collision, just keep two versions
80 GKernelPackage result(lhs);
81 for (const auto &p : rhs.m_backend_kernels)
83 result.m_backend_kernels[p.first].insert(p.second.begin(),
88 else GAPI_Assert(false);
89 return GKernelPackage();
92 std::pair<cv::gapi::GBackend, cv::GKernelImpl>
93 cv::gapi::GKernelPackage::lookup(const std::string &id,
94 const GLookupOrder &order) const
98 // If order is empty, return what comes first
99 auto it = std::find_if(m_backend_kernels.begin(),
100 m_backend_kernels.end(),
101 [&id](const M::value_type &p) {
102 return ade::util::contains(p.second, id);
104 if (it != m_backend_kernels.end())
106 // FIXME: Two lookups!
107 return std::make_pair(it->first, it->second.find(id)->second);
112 // There is order, so:
113 // 1. Limit search scope only to specified backends
114 // FIXME: Currently it is not configurable if search can fall-back
115 // to other backends (not listed in order) if kernel hasn't been found
116 // in the look-up list
117 // 2. Query backends in the specified order
118 for (const auto &selected_backend : order)
120 const auto kernels_it = m_backend_kernels.find(selected_backend);
121 if (kernels_it == m_backend_kernels.end())
123 GAPI_LOG_WARNING(NULL,
125 << &selected_backend.priv() // FIXME: name instead
126 << " was listed in lookup list but was not found "
130 if (ade::util::contains(kernels_it->second, id))
132 // FIXME: two lookups!
133 return std::make_pair(selected_backend, kernels_it->second.find(id)->second);
138 // If reached here, kernel was not found among selected backends.
139 util::throw_error(std::logic_error("Kernel " + id + " was not found"));
142 std::vector<cv::gapi::GBackend> cv::gapi::GKernelPackage::backends() const
144 std::vector<cv::gapi::GBackend> result;
145 for (const auto &p : m_backend_kernels) result.emplace_back(p.first);