Path: blob/master/modules/gapi/src/executor/gexecutor.cpp
16339 views
// This file is part of OpenCV project.1// It is subject to the license terms in the LICENSE file found in the top-level directory2// of this distribution and at http://opencv.org/license.html.3//4// Copyright (C) 2018 Intel Corporation567#include "precomp.hpp"89#include <iostream>1011#include <ade/util/zip_range.hpp>1213#include "opencv2/gapi/opencv_includes.hpp"14#include "executor/gexecutor.hpp"1516cv::gimpl::GExecutor::GExecutor(std::unique_ptr<ade::Graph> &&g_model)17: m_orig_graph(std::move(g_model))18, m_island_graph(GModel::Graph(*m_orig_graph).metadata()19.get<IslandModel>().model)20, m_gm(*m_orig_graph)21, m_gim(*m_island_graph)22{23// NB: Right now GIslandModel is acyclic, so for a naive execution,24// simple unrolling to a list of triggers is enough2526// Naive execution model is similar to current CPU (OpenCV) plugin27// execution model:28// 1. Allocate all internal resources first (NB - CPU plugin doesn't do it)29// 2. Put input/output GComputation arguments to the storage30// 3. For every Island, prepare vectors of input/output parameter descs31// 4. Iterate over a list of operations (sorted in the topological order)32// 5. For every operation, form a list of input/output data objects33// 6. Run GIslandExecutable34// 7. writeBack3536m_ops.reserve(m_gim.nodes().size());37auto sorted = m_gim.metadata().get<ade::passes::TopologicalSortData>();38for (auto nh : sorted.nodes())39{40switch (m_gim.metadata(nh).get<NodeKind>().k)41{42case NodeKind::ISLAND:43{44std::vector<RcDesc> input_rcs;45std::vector<RcDesc> output_rcs;46input_rcs.reserve(nh->inNodes().size());47output_rcs.reserve(nh->outNodes().size());4849auto xtract = [&](ade::NodeHandle slot_nh, std::vector<RcDesc> &vec) {50const auto orig_data_nh51= m_gim.metadata(slot_nh).get<DataSlot>().original_data_node;52const auto &orig_data_info53= m_gm.metadata(orig_data_nh).get<Data>();54vec.emplace_back(RcDesc{ orig_data_info.rc55, orig_data_info.shape56, orig_data_info.ctor});57};58// (3)59for (auto in_slot_nh : nh->inNodes()) xtract(in_slot_nh, input_rcs);60for (auto out_slot_nh : nh->outNodes()) xtract(out_slot_nh, output_rcs);61m_ops.emplace_back(OpDesc{ std::move(input_rcs)62, std::move(output_rcs)63, m_gim.metadata(nh).get<IslandExec>().object});64}65break;6667case NodeKind::SLOT:68{69const auto orig_data_nh70= m_gim.metadata(nh).get<DataSlot>().original_data_node;71// (1)72initResource(orig_data_nh);73m_slots.emplace_back(DataDesc{nh, orig_data_nh});74}75break;7677default:78GAPI_Assert(false);79break;80} // switch(kind)81} // for(gim nodes)82}8384void cv::gimpl::GExecutor::initResource(const ade::NodeHandle &orig_nh)85{86const Data &d = m_gm.metadata(orig_nh).get<Data>();8788if ( d.storage != Data::Storage::INTERNAL89&& d.storage != Data::Storage::CONST)90return;9192// INTERNALS+CONST only! no need to allocate/reset output objects93// to as it is bound externally (e.g. already in the m_res)9495switch (d.shape)96{97case GShape::GMAT:98{99const auto desc = util::get<cv::GMatDesc>(d.meta);100const auto type = CV_MAKETYPE(desc.depth, desc.chan);101m_res.slot<cv::gapi::own::Mat>()[d.rc].create(desc.size, type);102}103break;104105case GShape::GSCALAR:106if (d.storage == Data::Storage::CONST)107{108auto rc = RcDesc{d.rc, d.shape, d.ctor};109magazine::bindInArg(m_res, rc, m_gm.metadata(orig_nh).get<ConstValue>().arg);110}111break;112113case GShape::GARRAY:114// Constructed on Reset, do nothing here115break;116117default:118GAPI_Assert(false);119}120}121122void cv::gimpl::GExecutor::run(cv::gimpl::GRuntimeArgs &&args)123{124// (2)125const auto proto = m_gm.metadata().get<Protocol>();126127// Basic check if input/output arguments are correct128// FIXME: Move to GCompiled (do once for all GExecutors)129if (proto.inputs.size() != args.inObjs.size()) // TODO: Also check types130{131util::throw_error(std::logic_error132("Computation's input protocol doesn\'t "133"match actual arguments!"));134}135if (proto.outputs.size() != args.outObjs.size()) // TODO: Also check types136{137util::throw_error(std::logic_error138("Computation's output protocol doesn\'t "139"match actual arguments!"));140}141142namespace util = ade::util;143144//ensure that output Mat parameters are correctly allocated145for (auto index : util::iota(proto.out_nhs.size()) ) //FIXME: avoid copy of NodeHandle and GRunRsltComp ?146{147auto& nh = proto.out_nhs.at(index);148const Data &d = m_gm.metadata(nh).get<Data>();149if (d.shape == GShape::GMAT)150{151using cv::util::get;152const auto desc = get<cv::GMatDesc>(d.meta);153const auto type = CV_MAKETYPE(desc.depth, desc.chan);154155#if !defined(GAPI_STANDALONE)156// Building as part of OpenCV - follow OpenCV behavior157// if output buffer is not enough to hold the result, reallocate it158auto& out_mat = *get<cv::Mat*>(args.outObjs.at(index));159out_mat.create(cv::gapi::own::to_ocv(desc.size), type);160#else161// Building standalone - output buffer should always exist,162// and _exact_ match our inferred metadata163auto& out_mat = *get<cv::gapi::own::Mat*>(args.outObjs.at(index));164GAPI_Assert( out_mat.type() == type165&& out_mat.data != nullptr166&& out_mat.rows == desc.size.height167&& out_mat.cols == desc.size.width)168#endif // !defined(GAPI_STANDALONE)169}170}171// Update storage with user-passed objects172for (auto it : ade::util::zip(ade::util::toRange(proto.inputs),173ade::util::toRange(args.inObjs)))174{175magazine::bindInArg(m_res, std::get<0>(it), std::get<1>(it));176}177for (auto it : ade::util::zip(ade::util::toRange(proto.outputs),178ade::util::toRange(args.outObjs)))179{180magazine::bindOutArg(m_res, std::get<0>(it), std::get<1>(it));181}182183// Reset internal data184for (auto &sd : m_slots)185{186const auto& data = m_gm.metadata(sd.data_nh).get<Data>();187magazine::resetInternalData(m_res, data);188}189190// Run the script191for (auto &op : m_ops)192{193// (5)194using InObj = GIslandExecutable::InObj;195using OutObj = GIslandExecutable::OutObj;196std::vector<InObj> in_objs;197std::vector<OutObj> out_objs;198in_objs.reserve (op.in_objects.size());199out_objs.reserve(op.out_objects.size());200201for (const auto &rc : op.in_objects)202{203in_objs.emplace_back(InObj{rc, magazine::getArg(m_res, rc)});204}205for (const auto &rc : op.out_objects)206{207out_objs.emplace_back(OutObj{rc, magazine::getObjPtr(m_res, rc)});208}209210// (6)211op.isl_exec->run(std::move(in_objs), std::move(out_objs));212}213214// (7)215for (auto it : ade::util::zip(ade::util::toRange(proto.outputs),216ade::util::toRange(args.outObjs)))217{218magazine::writeBack(m_res, std::get<0>(it), std::get<1>(it));219}220}221222const cv::gimpl::GModel::Graph& cv::gimpl::GExecutor::model() const223{224return m_gm;225}226227228