Merge pull request #13851 from TolyaTalamanov:at/new-kernel-package-design
G-API: Kernel package design (#13851) * Remove cv::unite_policy from API * Add check that all id in kernel package are unique * Refactor checker id procedure * Remove cv::gapi::GLookupOrder from API * Implement cv::gapi::use_only * Fix samples * Fix docs * Fix comments to review * Remove unite_policy * Fix GKernelPackage::backends() * Fix comments to review * Fix all_unique * Fix comments to review * Fix comments to review * Remove out of date tests
This commit is contained in:
committed by
Alexander Alekhin
parent
de977cc9c8
commit
935c02c0a3
@@ -20,128 +20,73 @@
|
||||
// GKernelPackage public implementation ////////////////////////////////////////
|
||||
void cv::gapi::GKernelPackage::remove(const cv::gapi::GBackend& backend)
|
||||
{
|
||||
m_backend_kernels.erase(backend);
|
||||
std::vector<std::string> id_deleted_kernels;
|
||||
for (const auto& p : m_id_kernels)
|
||||
{
|
||||
if (p.second.first == backend)
|
||||
{
|
||||
id_deleted_kernels.push_back(p.first);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& kernel_id : id_deleted_kernels)
|
||||
{
|
||||
m_id_kernels.erase(kernel_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool cv::gapi::GKernelPackage::includesAPI(const std::string &id) const
|
||||
{
|
||||
// In current form not very efficient (n * log n)
|
||||
auto it = std::find_if(m_backend_kernels.begin(),
|
||||
m_backend_kernels.end(),
|
||||
[&id](const M::value_type &p) {
|
||||
return ade::util::contains(p.second, id);
|
||||
});
|
||||
return (it != m_backend_kernels.end());
|
||||
return ade::util::contains(m_id_kernels, id);
|
||||
}
|
||||
|
||||
void cv::gapi::GKernelPackage::removeAPI(const std::string &id)
|
||||
{
|
||||
for (auto &bk : m_backend_kernels)
|
||||
bk.second.erase(id);
|
||||
m_id_kernels.erase(id);
|
||||
}
|
||||
|
||||
std::size_t cv::gapi::GKernelPackage::size() const
|
||||
{
|
||||
return std::accumulate(m_backend_kernels.begin(),
|
||||
m_backend_kernels.end(),
|
||||
static_cast<std::size_t>(0u),
|
||||
[](std::size_t acc, const M::value_type& v) {
|
||||
return acc + v.second.size();
|
||||
});
|
||||
return m_id_kernels.size();
|
||||
}
|
||||
|
||||
cv::gapi::GKernelPackage cv::gapi::combine(const GKernelPackage &lhs,
|
||||
const GKernelPackage &rhs,
|
||||
const cv::unite_policy policy)
|
||||
const GKernelPackage &rhs)
|
||||
{
|
||||
|
||||
if (policy == cv::unite_policy::REPLACE)
|
||||
{
|
||||
// REPLACE policy: if there is a collision, prefer RHS
|
||||
// to LHS
|
||||
// If there is a collision, prefer RHS to LHS
|
||||
// since RHS package has a precedense, start with its copy
|
||||
GKernelPackage result(rhs);
|
||||
// now iterate over LHS package and put kernel if and only
|
||||
// if there's no such one
|
||||
for (const auto &backend : lhs.m_backend_kernels)
|
||||
for (const auto& kernel : lhs.m_id_kernels)
|
||||
{
|
||||
for (const auto &kimpl : backend.second)
|
||||
if (!result.includesAPI(kernel.first))
|
||||
{
|
||||
if (!result.includesAPI(kimpl.first))
|
||||
result.m_backend_kernels[backend.first].insert(kimpl);
|
||||
result.m_id_kernels.emplace(kernel.first, kernel.second);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else if (policy == cv::unite_policy::KEEP)
|
||||
{
|
||||
// KEEP policy: if there is a collision, just keep two versions
|
||||
// of a kernel
|
||||
GKernelPackage result(lhs);
|
||||
for (const auto &p : rhs.m_backend_kernels)
|
||||
{
|
||||
result.m_backend_kernels[p.first].insert(p.second.begin(),
|
||||
p.second.end());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else GAPI_Assert(false);
|
||||
return GKernelPackage();
|
||||
}
|
||||
|
||||
std::pair<cv::gapi::GBackend, cv::GKernelImpl>
|
||||
cv::gapi::GKernelPackage::lookup(const std::string &id,
|
||||
const GLookupOrder &order) const
|
||||
cv::gapi::GKernelPackage::lookup(const std::string &id) const
|
||||
{
|
||||
if (order.empty())
|
||||
auto kernel_it = m_id_kernels.find(id);
|
||||
if (kernel_it != m_id_kernels.end())
|
||||
{
|
||||
// If order is empty, return what comes first
|
||||
auto it = std::find_if(m_backend_kernels.begin(),
|
||||
m_backend_kernels.end(),
|
||||
[&id](const M::value_type &p) {
|
||||
return ade::util::contains(p.second, id);
|
||||
});
|
||||
if (it != m_backend_kernels.end())
|
||||
{
|
||||
// FIXME: Two lookups!
|
||||
return std::make_pair(it->first, it->second.find(id)->second);
|
||||
}
|
||||
return kernel_it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
// There is order, so:
|
||||
// 1. Limit search scope only to specified backends
|
||||
// FIXME: Currently it is not configurable if search can fall-back
|
||||
// to other backends (not listed in order) if kernel hasn't been found
|
||||
// in the look-up list
|
||||
// 2. Query backends in the specified order
|
||||
for (const auto &selected_backend : order)
|
||||
{
|
||||
const auto kernels_it = m_backend_kernels.find(selected_backend);
|
||||
if (kernels_it == m_backend_kernels.end())
|
||||
{
|
||||
GAPI_LOG_WARNING(NULL,
|
||||
"Backend "
|
||||
<< &selected_backend.priv() // FIXME: name instead
|
||||
<< " was listed in lookup list but was not found "
|
||||
"in the package");
|
||||
continue;
|
||||
}
|
||||
if (ade::util::contains(kernels_it->second, id))
|
||||
{
|
||||
// FIXME: two lookups!
|
||||
return std::make_pair(selected_backend, kernels_it->second.find(id)->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If reached here, kernel was not found among selected backends.
|
||||
// If reached here, kernel was not found.
|
||||
util::throw_error(std::logic_error("Kernel " + id + " was not found"));
|
||||
}
|
||||
|
||||
std::vector<cv::gapi::GBackend> cv::gapi::GKernelPackage::backends() const
|
||||
{
|
||||
std::vector<cv::gapi::GBackend> result;
|
||||
for (const auto &p : m_backend_kernels) result.emplace_back(p.first);
|
||||
return result;
|
||||
using kernel_type = std::pair<std::string, std::pair<cv::gapi::GBackend, cv::GKernelImpl>>;
|
||||
std::unordered_set<cv::gapi::GBackend> unique_set;
|
||||
ade::util::transform(m_id_kernels, std::inserter(unique_set, unique_set.end()),
|
||||
[](const kernel_type& k) { return k.second.first; });
|
||||
|
||||
return std::vector<cv::gapi::GBackend>(unique_set.begin(), unique_set.end());
|
||||
}
|
||||
|
||||
@@ -48,16 +48,19 @@ namespace
|
||||
{
|
||||
cv::gapi::GKernelPackage getKernelPackage(cv::GCompileArgs &args)
|
||||
{
|
||||
auto has_use_only = cv::gimpl::getCompileArg<cv::gapi::use_only>(args);
|
||||
if (has_use_only)
|
||||
return has_use_only.value().pkg;
|
||||
|
||||
static auto ocv_pkg =
|
||||
#if !defined(GAPI_STANDALONE)
|
||||
combine(cv::gapi::core::cpu::kernels(),
|
||||
cv::gapi::imgproc::cpu::kernels(),
|
||||
cv::unite_policy::KEEP);
|
||||
cv::gapi::imgproc::cpu::kernels());
|
||||
#else
|
||||
cv::gapi::GKernelPackage();
|
||||
#endif // !defined(GAPI_STANDALONE)
|
||||
auto user_pkg = cv::gimpl::getCompileArg<cv::gapi::GKernelPackage>(args);
|
||||
return combine(ocv_pkg, user_pkg.value_or(cv::gapi::GKernelPackage{}), cv::unite_policy::REPLACE);
|
||||
return combine(ocv_pkg, user_pkg.value_or(cv::gapi::GKernelPackage{}));
|
||||
}
|
||||
|
||||
cv::util::optional<std::string> getGraphDumpDirectory(cv::GCompileArgs& args)
|
||||
@@ -87,7 +90,6 @@ cv::gimpl::GCompiler::GCompiler(const cv::GComputation &c,
|
||||
{
|
||||
using namespace std::placeholders;
|
||||
m_all_kernels = getKernelPackage(m_args);
|
||||
auto lookup_order = getCompileArg<gapi::GLookupOrder>(m_args).value_or(gapi::GLookupOrder());
|
||||
auto dump_path = getGraphDumpDirectory(m_args);
|
||||
|
||||
m_e.addPassStage("init");
|
||||
@@ -107,8 +109,7 @@ cv::gimpl::GCompiler::GCompiler(const cv::GComputation &c,
|
||||
|
||||
m_e.addPassStage("kernels");
|
||||
m_e.addPass("kernels", "resolve_kernels", std::bind(passes::resolveKernels, _1,
|
||||
std::ref(m_all_kernels), // NB: and not copied here
|
||||
lookup_order));
|
||||
std::ref(m_all_kernels))); // NB: and not copied here
|
||||
m_e.addPass("kernels", "check_islands_content", passes::checkIslandsContent);
|
||||
|
||||
m_e.addPassStage("meta");
|
||||
|
||||
@@ -101,8 +101,7 @@ namespace
|
||||
// This pass, given the kernel package, selects a kernel implementation
|
||||
// for every operation in the graph
|
||||
void cv::gimpl::passes::resolveKernels(ade::passes::PassContext &ctx,
|
||||
const gapi::GKernelPackage &kernels,
|
||||
const gapi::GLookupOrder &order)
|
||||
const gapi::GKernelPackage &kernels)
|
||||
{
|
||||
std::unordered_set<cv::gapi::GBackend> active_backends;
|
||||
|
||||
@@ -114,8 +113,7 @@ void cv::gimpl::passes::resolveKernels(ade::passes::PassContext &ctx,
|
||||
auto &op = gr.metadata(nh).get<Op>();
|
||||
cv::gapi::GBackend selected_backend;
|
||||
cv::GKernelImpl selected_impl;
|
||||
std::tie(selected_backend, selected_impl)
|
||||
= kernels.lookup(op.k.name, order);
|
||||
std::tie(selected_backend, selected_impl) = kernels.lookup(op.k.name);
|
||||
|
||||
selected_backend.priv().unpackKernel(ctx.graph, nh, selected_impl);
|
||||
op.backend = selected_backend;
|
||||
|
||||
@@ -44,9 +44,8 @@ void storeResultingMeta(ade::passes::PassContext &ctx);
|
||||
void expandKernels(ade::passes::PassContext &ctx,
|
||||
const gapi::GKernelPackage& kernels);
|
||||
|
||||
void resolveKernels(ade::passes::PassContext &ctx,
|
||||
const gapi::GKernelPackage &kernels,
|
||||
const gapi::GLookupOrder &order);
|
||||
void resolveKernels(ade::passes::PassContext &ctx,
|
||||
const gapi::GKernelPackage &kernels);
|
||||
|
||||
void fuseIslands(ade::passes::PassContext &ctx);
|
||||
void syncIslandTags(ade::passes::PassContext &ctx);
|
||||
|
||||
Reference in New Issue
Block a user