mirror of
https://github.com/opencv/opencv.git
synced 2025-01-18 22:44:02 +08:00
Introduce a new abstraction layer over island input/output data
- Port GExecutor to this new interface
This commit is contained in:
parent
277f0d270f
commit
1b5730a799
@ -153,6 +153,8 @@ public:
|
||||
virtual void run(std::vector<InObj> &&input_objs,
|
||||
std::vector<OutObj> &&output_objs) override;
|
||||
|
||||
using GIslandExecutable::run; // (IInput&, IOutput&) version
|
||||
|
||||
void run(std::vector<InObj> &input_objs,
|
||||
std::vector<OutObj> &output_objs);
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include <ade/util/checked_cast.hpp>
|
||||
#include <ade/util/zip_range.hpp> // zip_range, indexed
|
||||
|
||||
#include "api/gbackend_priv.hpp" // GBackend::Priv().compile()
|
||||
#include "compiler/gmodel.hpp"
|
||||
@ -319,5 +320,33 @@ ade::NodeHandle GIslandModel::producerOf(const ConstGraph &g, ade::NodeHandle &d
|
||||
return ade::NodeHandle();
|
||||
}
|
||||
|
||||
void GIslandExecutable::run(GIslandExecutable::IInput &in, GIslandExecutable::IOutput &out)
|
||||
{
|
||||
// Default implementation: just reuse the existing old-fashioned run
|
||||
// Build a single synchronous execution frame for it.
|
||||
std::vector<InObj> in_objs;
|
||||
std::vector<OutObj> out_objs;
|
||||
const auto &in_desc = in.desc();
|
||||
const auto &out_desc = out.desc();
|
||||
const auto in_vector = in.get(); // FIXME: passing temporary objects to toRange() leads to issues
|
||||
in_objs.reserve(in_desc.size());
|
||||
out_objs.reserve(out_desc.size());
|
||||
for (auto &&it: ade::util::zip(ade::util::toRange(in_desc),
|
||||
ade::util::toRange(in_vector)))
|
||||
{
|
||||
in_objs.emplace_back(std::get<0>(it), std::get<1>(it));
|
||||
}
|
||||
for (auto &&it: ade::util::indexed(ade::util::toRange(out_desc)))
|
||||
{
|
||||
out_objs.emplace_back(ade::util::value(it),
|
||||
out.get(ade::util::checked_cast<int>(ade::util::index(it))));
|
||||
}
|
||||
run(std::move(in_objs), std::move(out_objs));
|
||||
for (auto &&it: out_objs)
|
||||
{
|
||||
out.post(std::move(it.second)); // report output objects as "ready" to the executor
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cv
|
||||
} // namespace gimpl
|
||||
|
@ -89,33 +89,58 @@ protected:
|
||||
util::optional<std::string> m_user_tag;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// GIslandExecutable - a backend-specific thing which executes
|
||||
// contents of an Island
|
||||
// * Is instantiated by the last step of the Islands fusion procedure;
|
||||
// * Is orchestrated by a GExecutor instance.
|
||||
//
|
||||
|
||||
class GIslandExecutable
|
||||
{
|
||||
public:
|
||||
using InObj = std::pair<RcDesc, cv::GRunArg>;
|
||||
using OutObj = std::pair<RcDesc, cv::GRunArgP>;
|
||||
|
||||
class IODesc;
|
||||
struct IInput;
|
||||
struct IOutput;
|
||||
|
||||
// FIXME: now run() requires full input vector to be available.
|
||||
// actually, parts of subgraph may execute even if there's no all data
|
||||
// slots in place.
|
||||
// TODO: Add partial execution capabilities
|
||||
// TODO: This method is now obsolette and is here for backwards
|
||||
// compatibility only. Use (implement) the new run instead.
|
||||
virtual void run(std::vector<InObj> &&input_objs,
|
||||
std::vector<OutObj> &&output_objs) = 0;
|
||||
|
||||
// Let the island execute. I/O data is obtained from/submitted to
|
||||
// in/out objects.
|
||||
virtual void run(IInput &in, IOutput &out);
|
||||
|
||||
virtual bool canReshape() const = 0;
|
||||
virtual void reshape(ade::Graph& g, const GCompileArgs& args) = 0;
|
||||
|
||||
virtual ~GIslandExecutable() = default;
|
||||
};
|
||||
|
||||
class GIslandExecutable::IODesc {
|
||||
std::vector<cv::gimpl::RcDesc> d;
|
||||
public:
|
||||
void set(std::vector<cv::gimpl::RcDesc> &&newd) { d = std::move(newd); }
|
||||
void set(const std::vector<cv::gimpl::RcDesc> &newd) { d = newd; }
|
||||
const std::vector<cv::gimpl::RcDesc> &desc() const { return d; }
|
||||
};
|
||||
struct GIslandExecutable::IInput: public GIslandExecutable::IODesc {
|
||||
virtual ~IInput() = default;
|
||||
virtual cv::GRunArgs get() = 0; // Get a new input vector (blocking)
|
||||
virtual cv::GRunArgs try_get() = 0; // Get a new input vector (non-blocking)
|
||||
};
|
||||
struct GIslandExecutable::IOutput: public GIslandExecutable::IODesc {
|
||||
virtual ~IOutput() = default;
|
||||
virtual GRunArgP get(int idx) = 0; // Allocate (wrap) a new data object for output idx
|
||||
virtual void post(GRunArgP&&) = 0; // Release the object back to the framework (mark available)
|
||||
};
|
||||
|
||||
// GIslandEmitter - a backend-specific thing which feeds data into
|
||||
// the pipeline. This one is just an interface, implementations are executor-defined.
|
||||
class GIslandEmitter
|
||||
|
@ -122,6 +122,29 @@ void cv::gimpl::GExecutor::initResource(const ade::NodeHandle &orig_nh)
|
||||
}
|
||||
}
|
||||
|
||||
class cv::gimpl::GExecutor::Input final: public cv::gimpl::GIslandExecutable::IInput
|
||||
{
|
||||
cv::gimpl::Mag &mag;
|
||||
virtual cv::GRunArgs get() override
|
||||
{
|
||||
cv::GRunArgs res;
|
||||
for (const auto &rc : desc()) { res.emplace_back(magazine::getArg(mag, rc)); }
|
||||
return res;
|
||||
}
|
||||
virtual cv::GRunArgs try_get() override { return get(); }
|
||||
public:
|
||||
Input(cv::gimpl::Mag &m, const std::vector<RcDesc> &rcs) : mag(m) { set(rcs); }
|
||||
};
|
||||
|
||||
class cv::gimpl::GExecutor::Output final: public cv::gimpl::GIslandExecutable::IOutput
|
||||
{
|
||||
cv::gimpl::Mag &mag;
|
||||
virtual GRunArgP get(int idx) override { return magazine::getObjPtr(mag, desc()[idx]); }
|
||||
virtual void post(GRunArgP&&) override { } // Do nothing here
|
||||
public:
|
||||
Output(cv::gimpl::Mag &m, const std::vector<RcDesc> &rcs) : mag(m) { set(rcs); }
|
||||
};
|
||||
|
||||
void cv::gimpl::GExecutor::run(cv::gimpl::GRuntimeArgs &&args)
|
||||
{
|
||||
// (2)
|
||||
@ -144,8 +167,9 @@ void cv::gimpl::GExecutor::run(cv::gimpl::GRuntimeArgs &&args)
|
||||
|
||||
namespace util = ade::util;
|
||||
|
||||
//ensure that output Mat parameters are correctly allocated
|
||||
for (auto index : util::iota(proto.out_nhs.size()) ) //FIXME: avoid copy of NodeHandle and GRunRsltComp ?
|
||||
// ensure that output Mat parameters are correctly allocated
|
||||
// FIXME: avoid copy of NodeHandle and GRunRsltComp ?
|
||||
for (auto index : util::iota(proto.out_nhs.size()))
|
||||
{
|
||||
auto& nh = proto.out_nhs.at(index);
|
||||
const Data &d = m_gm.metadata(nh).get<Data>();
|
||||
@ -162,8 +186,9 @@ void cv::gimpl::GExecutor::run(cv::gimpl::GRuntimeArgs &&args)
|
||||
};
|
||||
|
||||
#if !defined(GAPI_STANDALONE)
|
||||
// Building as part of OpenCV - follow OpenCV behavior
|
||||
// In the case of cv::Mat if output buffer is not enough to hold the result, reallocate it
|
||||
// Building as part of OpenCV - follow OpenCV behavior In
|
||||
// the case of cv::Mat if output buffer is not enough to
|
||||
// hold the result, reallocate it
|
||||
if (cv::util::holds_alternative<cv::Mat*>(args.outObjs.at(index)))
|
||||
{
|
||||
auto& out_mat = *get<cv::Mat*>(args.outObjs.at(index));
|
||||
@ -204,24 +229,9 @@ void cv::gimpl::GExecutor::run(cv::gimpl::GRuntimeArgs &&args)
|
||||
for (auto &op : m_ops)
|
||||
{
|
||||
// (5)
|
||||
using InObj = GIslandExecutable::InObj;
|
||||
using OutObj = GIslandExecutable::OutObj;
|
||||
std::vector<InObj> in_objs;
|
||||
std::vector<OutObj> out_objs;
|
||||
in_objs.reserve (op.in_objects.size());
|
||||
out_objs.reserve(op.out_objects.size());
|
||||
|
||||
for (const auto &rc : op.in_objects)
|
||||
{
|
||||
in_objs.emplace_back(InObj{rc, magazine::getArg(m_res, rc)});
|
||||
}
|
||||
for (const auto &rc : op.out_objects)
|
||||
{
|
||||
out_objs.emplace_back(OutObj{rc, magazine::getObjPtr(m_res, rc)});
|
||||
}
|
||||
|
||||
// (6)
|
||||
op.isl_exec->run(std::move(in_objs), std::move(out_objs));
|
||||
Input i{m_res, op.in_objects};
|
||||
Output o{m_res, op.out_objects};
|
||||
op.isl_exec->run(i, o);
|
||||
}
|
||||
|
||||
// (7)
|
||||
|
@ -77,6 +77,9 @@ protected:
|
||||
};
|
||||
std::vector<DataDesc> m_slots;
|
||||
|
||||
class Input;
|
||||
class Output;
|
||||
|
||||
Mag m_res;
|
||||
|
||||
void initResource(const ade::NodeHandle &orig_nh); // FIXME: shouldn't it be RcDesc?
|
||||
|
Loading…
Reference in New Issue
Block a user