Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / fluid / modules / gapi / src / api / gkernel.cpp
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.
4 //
5 // Copyright (C) 2018-2019 Intel Corporation
6
7
8 #include "precomp.hpp"
9 #include <iostream> // cerr
10 #include <functional> // hash
11 #include <numeric> // accumulate
12
13 #include <ade/util/algorithm.hpp>
14
15 #include "logger.hpp"
16 #include "opencv2/gapi/gkernel.hpp"
17
18 #include "api/gbackend_priv.hpp"
19
20 // GKernelPackage public implementation ////////////////////////////////////////
21 void cv::gapi::GKernelPackage::remove(const cv::gapi::GBackend& backend)
22 {
23     m_backend_kernels.erase(backend);
24 }
25
26 bool cv::gapi::GKernelPackage::includesAPI(const std::string &id) const
27 {
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);
33                            });
34     return (it != m_backend_kernels.end());
35 }
36
37 void cv::gapi::GKernelPackage::removeAPI(const std::string &id)
38 {
39     for (auto &bk : m_backend_kernels)
40         bk.second.erase(id);
41 }
42
43 std::size_t cv::gapi::GKernelPackage::size() const
44 {
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();
50                            });
51 }
52
53 cv::gapi::GKernelPackage cv::gapi::combine(const GKernelPackage  &lhs,
54                                            const GKernelPackage  &rhs,
55                                            const cv::unite_policy policy)
56 {
57
58     if (policy == cv::unite_policy::REPLACE)
59     {
60         // REPLACE policy: if there is a collision, prefer RHS
61         // to LHS
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)
67         {
68             for (const auto &kimpl : backend.second)
69             {
70                 if (!result.includesAPI(kimpl.first))
71                     result.m_backend_kernels[backend.first].insert(kimpl);
72             }
73         }
74         return result;
75     }
76     else if (policy == cv::unite_policy::KEEP)
77     {
78         // KEEP policy: if there is a collision, just keep two versions
79         // of a kernel
80         GKernelPackage result(lhs);
81         for (const auto &p : rhs.m_backend_kernels)
82         {
83             result.m_backend_kernels[p.first].insert(p.second.begin(),
84                                                      p.second.end());
85         }
86         return result;
87     }
88     else GAPI_Assert(false);
89     return GKernelPackage();
90 }
91
92 std::pair<cv::gapi::GBackend, cv::GKernelImpl>
93 cv::gapi::GKernelPackage::lookup(const std::string &id,
94                                  const GLookupOrder &order) const
95 {
96     if (order.empty())
97     {
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);
103                                });
104         if (it != m_backend_kernels.end())
105         {
106             // FIXME: Two lookups!
107             return std::make_pair(it->first, it->second.find(id)->second);
108         }
109     }
110     else
111     {
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)
119         {
120             const auto kernels_it = m_backend_kernels.find(selected_backend);
121             if (kernels_it == m_backend_kernels.end())
122             {
123                 GAPI_LOG_WARNING(NULL,
124                                  "Backend "
125                                   << &selected_backend.priv() // FIXME: name instead
126                                   << " was listed in lookup list but was not found "
127                                      "in the package");
128                 continue;
129             }
130             if (ade::util::contains(kernels_it->second, id))
131             {
132                 // FIXME: two lookups!
133                 return std::make_pair(selected_backend, kernels_it->second.find(id)->second);
134             }
135         }
136     }
137
138     // If reached here, kernel was not found among selected backends.
139     util::throw_error(std::logic_error("Kernel " + id + " was not found"));
140 }
141
142 std::vector<cv::gapi::GBackend> cv::gapi::GKernelPackage::backends() const
143 {
144     std::vector<cv::gapi::GBackend> result;
145     for (const auto &p : m_backend_kernels) result.emplace_back(p.first);
146     return result;
147 }