diff --git a/include/aidge/backend/OperatorImpl.hpp b/include/aidge/backend/OperatorImpl.hpp index 5aa2829e16f612b0867ab69feccb829ba2095e1b..d10270b62bb75412a6cbd9203b9b7a3fe220e5aa 100644 --- a/include/aidge/backend/OperatorImpl.hpp +++ b/include/aidge/backend/OperatorImpl.hpp @@ -20,7 +20,7 @@ namespace Aidge { class OperatorImpl { public: virtual void forward(){}; - virtual void backward() {} + virtual void backward(){}; /** * @brief Minimum amount of data from a specific input required by the @@ -46,13 +46,19 @@ public: virtual NbElts_t getNbConsumedData(const IOIndex_t inputIdx) const = 0; /** - * @brief TOtal amount of produced data ready to be used on a specific output. + * @brief Total amount of produced data ready to be used on a specific output. * * @param outputIdx Index of the output analysed. * @return DimSize_t */ virtual NbElts_t getNbProducedData(const IOIndex_t outputIdx) const = 0; + /** + * @brief Update the Consummer Producer system by simulating the consumption and production of i/o + * + */ + virtual void updateConsummerProducer() = 0; + virtual ~OperatorImpl() = default; }; } // namespace Aidge diff --git a/include/aidge/graph/OpArgs.hpp b/include/aidge/graph/OpArgs.hpp index 560c3a02c641c29526752dbf352905d0ded32a7e..9d1ba6fd1e1df594634bfd93a24663ff178b7ee6 100644 --- a/include/aidge/graph/OpArgs.hpp +++ b/include/aidge/graph/OpArgs.hpp @@ -55,7 +55,7 @@ public: * @param inputs List of Node and GraphView to link sequentially. * @return std::shared_ptr<GraphView> Pointer to the generated view. */ -std::shared_ptr<GraphView> Sequential(std::initializer_list<OpArgs> inputs); +std::shared_ptr<GraphView> Sequential(std::vector<OpArgs> inputs); ///////////////////////////// // Parallel @@ -65,7 +65,7 @@ std::shared_ptr<GraphView> Sequential(std::initializer_list<OpArgs> inputs); * @param inputs List of Node and GraphView to link sequentially. * @return std::shared_ptr<GraphView> pointer to the generated view. */ -std::shared_ptr<GraphView> Parallel(std::initializer_list<OpArgs> inputs); +std::shared_ptr<GraphView> Parallel(std::vector<OpArgs> inputs); ///////////////////////////// // Residual @@ -79,8 +79,8 @@ std::shared_ptr<GraphView> Parallel(std::initializer_list<OpArgs> inputs); * @param inputs List of Node and GraphView to link sequentially. * @return std::shared_ptr<GraphView> pointer to the generated view. */ -std::shared_ptr<GraphView> Residual(std::initializer_list<OpArgs> inputs); +std::shared_ptr<GraphView> Residual(std::vector<OpArgs> inputs); } -#endif /* AIDGE_CORE_GRAPH_OPARGS_H_ */ \ No newline at end of file +#endif /* AIDGE_CORE_GRAPH_OPARGS_H_ */ diff --git a/include/aidge/operator/Operator.hpp b/include/aidge/operator/Operator.hpp index 30e1ce2a7f664485077282405ec60ddf49513cb5..36f846ddae329be28b8e51e2bff1580a509562e1 100644 --- a/include/aidge/operator/Operator.hpp +++ b/include/aidge/operator/Operator.hpp @@ -78,6 +78,8 @@ public: */ NbElts_t getNbProducedData(const IOIndex_t outputIdx) const; + void updateConsummerProducer(); + virtual void forward(); virtual void backward(); diff --git a/include/aidge/scheduler/Scheduler.hpp b/include/aidge/scheduler/Scheduler.hpp index 81b3f31662933fe4f59a17cdb0ee42441fb791bc..9916ee2004bd1aa9f33acf96d95cae4703f692df 100644 --- a/include/aidge/scheduler/Scheduler.hpp +++ b/include/aidge/scheduler/Scheduler.hpp @@ -43,6 +43,8 @@ public: }; ~SequentialScheduler() = default; + void generateScheduling(bool verbose = false); + /** * @brief Run the provided Computational Graph with a batch of data */ @@ -54,6 +56,15 @@ public: */ void saveSchedulingDiagram(const std::string& fileName) const; + /** + * @brief Return a vector of Node ordered by the order they are called by the scheduler + * + * @return std::vector<std::shared_ptr<Node>> + */ + std::vector<std::shared_ptr<Node>> getStaticScheduling(){ + return mStaticSchedule; + } + private: /** * @brief Set of layers receiving an input from currently processing layers @@ -63,9 +74,27 @@ private: */ std::set<std::shared_ptr<Node>> getConsumers(const std::set<std::shared_ptr<Node>>& producers) const; + /** + * @brief Shared ptr to the scheduled graph view + * + */ std::shared_ptr<GraphView> mGraphView; + /** + * @brief List of SchedulingElement (i.e: Nodes with their computation time) + * + */ std::vector<SchedulingElement> mScheduling; + /** + * @brief List of nodes ordered by their + * + */ + std::vector<std::shared_ptr<Node>> mStaticSchedule; + /** + * @brief Number of computation node (i.e: nb nodes != Producer) + * + */ + std::size_t mComputationNumber = 0; // TODO: Check if not inferable from mStaticSchedule }; } // namespace Aidge -#endif /* AIDGE_SCHEDULER_H_ */ \ No newline at end of file +#endif /* AIDGE_SCHEDULER_H_ */ diff --git a/python_binding/graph/pybind_OpArgs.cpp b/python_binding/graph/pybind_OpArgs.cpp index 305c0b73101a97c242413ff84a5ae099764e7e77..6ea89f91945ac44f2142c5b9e8440b11ec6a1663 100644 --- a/python_binding/graph/pybind_OpArgs.cpp +++ b/python_binding/graph/pybind_OpArgs.cpp @@ -10,19 +10,20 @@ ********************************************************************************/ #include <pybind11/pybind11.h> +#include <pybind11/stl.h> + #include "aidge/graph/OpArgs.hpp" #include "aidge/graph/Node.hpp" #include "aidge/graph/GraphView.hpp" -#include <pybind11/stl.h> -#include <pybind11/complex.h> -#include <pybind11/functional.h> -#include <pybind11/chrono.h> + namespace py = pybind11; namespace Aidge { void init_OpArgs(py::module& m){ py::class_<OpArgs, std::shared_ptr<OpArgs>>(m, "OpArgs") + .def(py::init<const std::shared_ptr<GraphView>&>(), py::arg("view_")) + .def(py::init<const std::shared_ptr<Node>&>(), py::arg("node_")) .def("node", &OpArgs::node) .def("view", &OpArgs::view) ; diff --git a/python_binding/operator/pybind_GenericOperator.cpp b/python_binding/operator/pybind_GenericOperator.cpp index ee3ee74c14e58dd5160cb041a123c329ab0bbb84..bec59eaf2cecdc7f64d1da07580116c4b3334992 100644 --- a/python_binding/operator/pybind_GenericOperator.cpp +++ b/python_binding/operator/pybind_GenericOperator.cpp @@ -22,7 +22,7 @@ namespace Aidge { void init_GenericOperator(py::module& m) { py::class_<GenericOperator_Op, std::shared_ptr<GenericOperator_Op>, Operator>(m, "GenericOperatorOp", py::multiple_inheritance()) - .def("get_parameter_type", &GenericOperator_Op::getParameterType) + .def("get_parameter_type", &GenericOperator_Op::getParameterType) .def("get_parameters_name", &GenericOperator_Op::getParametersName) .def("add_parameter", &GenericOperator_Op::addParameter<bool>) .def("add_parameter", &GenericOperator_Op::addParameter<int>) @@ -34,10 +34,10 @@ void init_GenericOperator(py::module& m) { .def("add_parameter", &GenericOperator_Op::addParameter<std::vector<std::string>>) .def("get_parameter", [](GenericOperator_Op& self, std::string key) -> py::object { /* - This getParameter method returns the good python type without having to have + This getParameter method returns the good python type without having to have prior knowledge of the parameter type. */ - py::object res = py::none(); + py::object res = py::none(); std::string paramType = self.getParameterType(key); if(paramType == typeid(int).name()) res = py::cast(self.getParameter<int>(key)); diff --git a/python_binding/scheduler/pybind_Scheduler.cpp b/python_binding/scheduler/pybind_Scheduler.cpp index 2490d5c55a497223b13bceee6772c2dd44e733ef..85479d41f51e74dee4079e78a37e7f3a520639e2 100644 --- a/python_binding/scheduler/pybind_Scheduler.cpp +++ b/python_binding/scheduler/pybind_Scheduler.cpp @@ -10,6 +10,7 @@ ********************************************************************************/ #include <pybind11/pybind11.h> +#include <pybind11/stl.h> #include "aidge/scheduler/Scheduler.hpp" #include "aidge/graph/GraphView.hpp" @@ -20,6 +21,8 @@ void init_Scheduler(py::module& m){ .def(py::init<std::shared_ptr<GraphView>&>(), py::arg("graph_view")) .def("forward", &SequentialScheduler::forward, py::arg("forward_dims")=true, py::arg("verbose")=false) .def("save_scheduling_diagram", &SequentialScheduler::saveSchedulingDiagram, py::arg("file_name")) + .def("generate_scheduling", &SequentialScheduler::generateScheduling, py::arg("verbose")=false) + .def("get_static_scheduling", &SequentialScheduler::getStaticScheduling) ; } } diff --git a/src/graph/OpArgs.cpp b/src/graph/OpArgs.cpp index f5f33fb049dec440f3bae412348c83e3427f06ce..124878fc45fe632d4a584e76a0eae6e7acfd53b9 100644 --- a/src/graph/OpArgs.cpp +++ b/src/graph/OpArgs.cpp @@ -14,13 +14,13 @@ #include "aidge/graph/OpArgs.hpp" -std::shared_ptr<Aidge::GraphView> Aidge::Sequential(std::initializer_list<OpArgs> inputs) { +std::shared_ptr<Aidge::GraphView> Aidge::Sequential(std::vector<OpArgs> inputs) { std::shared_ptr<GraphView> gv = std::make_shared<GraphView>(); for (const OpArgs& elt : inputs) { if(elt.node() != nullptr) { // >= to allow incomplete graphViews assert(static_cast<std::size_t>(elt.node()->getNbFreeDataInputs()) >= gv->outputNodes().size()); - /* + /* * /!\ mn.view()->outputNodes() is a set, order of Nodes cannot be guaranted. * Prefer a functional description for detailed inputs */ @@ -44,7 +44,7 @@ std::shared_ptr<Aidge::GraphView> Aidge::Sequential(std::initializer_list<OpArgs } -std::shared_ptr<Aidge::GraphView> Aidge::Parallel(std::initializer_list<OpArgs> inputs) { +std::shared_ptr<Aidge::GraphView> Aidge::Parallel(std::vector<OpArgs> inputs) { std::shared_ptr<GraphView> gv = std::make_shared<GraphView>(); for(const OpArgs& elt : inputs) { if (elt.node()!=nullptr) @@ -56,7 +56,7 @@ std::shared_ptr<Aidge::GraphView> Aidge::Parallel(std::initializer_list<OpArgs> } -std::shared_ptr<Aidge::GraphView> Aidge::Residual(std::initializer_list<OpArgs> inputs) { +std::shared_ptr<Aidge::GraphView> Aidge::Residual(std::vector<OpArgs> inputs) { std::shared_ptr<GraphView> gv = Sequential(inputs); assert(gv->outputNodes().size() == 1U && "Zero or more than one output Node for the GraphView, don't know which one to choose from for the residual connection"); std::shared_ptr<Node> lastNode = *gv->outputNodes().begin(); @@ -70,4 +70,4 @@ std::shared_ptr<Aidge::GraphView> Aidge::Residual(std::initializer_list<OpArgs> assert(lastNode->getNbFreeDataInputs()>=1); gv->addChild(lastNode, firstNode, 0U, gk_IODefaultIndex); return gv; -} \ No newline at end of file +} diff --git a/src/operator/Operator.cpp b/src/operator/Operator.cpp index 99b07235e2917527160f03af997747f02947dcf9..b3896b12143488275b2a064819595c380da62844 100644 --- a/src/operator/Operator.cpp +++ b/src/operator/Operator.cpp @@ -38,6 +38,9 @@ Aidge::NbElts_t Aidge::Operator::getNbConsumedData(Aidge::IOIndex_t inputIdx) co Aidge::NbElts_t Aidge::Operator::getNbProducedData(Aidge::IOIndex_t outputIdx) const { return mImpl->getNbProducedData(outputIdx); } +void Aidge::Operator::updateConsummerProducer(){ + mImpl->updateConsummerProducer(); +} void Aidge::Operator::forward() { mImpl->forward(); } diff --git a/src/scheduler/Scheduler.cpp b/src/scheduler/Scheduler.cpp index a8069fda9a3a2f4cbb999eeb3974230767069fb8..dc0768d2b6f7a1dd46fc0a8523b950011f7dcf5d 100644 --- a/src/scheduler/Scheduler.cpp +++ b/src/scheduler/Scheduler.cpp @@ -33,26 +33,19 @@ void drawProgressBar(double progress, int barWidth, const std::string& additiona fflush(stdout); } -// TODO: handle multiple inputs/outputs -void Aidge::SequentialScheduler::forward(bool frowardDims, bool verbose) { - if (frowardDims) {mGraphView->forwardDims(); } - - mScheduling.clear(); - +void Aidge::SequentialScheduler::generateScheduling(bool verbose) { // setup initial producers list - // add each Producer Node. - std::set<std::shared_ptr<Node>> computationOver; - std::size_t computationNumber = 0; + mComputationNumber = 0; std::set<std::shared_ptr<Node>> producers; for (const std::shared_ptr<Node>& nodePtr : mGraphView->getNodes()) { if (nodePtr->type() == "Producer") { producers.insert(nodePtr); } else { - ++computationNumber; + ++mComputationNumber; } } // add Data Input - // FIXME : shoudl be changed when the real system for providing + // FIXME : should be changed when the real system for providing // data is implemented for (const std::shared_ptr<Node>& nodePtr : mGraphView->inputNodes()) { for (const auto& parentPtr : nodePtr->getParents()) { @@ -112,21 +105,10 @@ void Aidge::SequentialScheduler::forward(bool frowardDims, bool verbose) { } } - // run sequencially every runnable consumers once - // TODO: handle memory allocation in scheduler - // TODO: optimize memory usage + // Push consumers in the list of nodes to run and update the consumer producer system for (const auto& runnable : runnableConsumers) { - if (verbose) - printf("run: %s\n", - (runnable->type() + "_" + std::to_string(reinterpret_cast<uintptr_t>(runnable.get()))).c_str()); - else - drawProgressBar(static_cast<float>(computationOver.size()) / static_cast<float>(computationNumber), 50, - (std::string("running ") + runnable->type() + "_" + - std::to_string(reinterpret_cast<uintptr_t>(runnable.get())))); - const auto tStart = std::chrono::high_resolution_clock::now(); - runnable->forward(); - const auto tEnd = std::chrono::high_resolution_clock::now(); - mScheduling.push_back(SchedulingElement(runnable, tStart, tEnd)); + runnable->getOperator()->updateConsummerProducer(); + mStaticSchedule.push_back(runnable); } // update producers and consumers list @@ -164,18 +146,6 @@ void Aidge::SequentialScheduler::forward(bool frowardDims, bool verbose) { } } - bool computationOverForConsumer = true; - for (IOIndex_t parentIDi = 0; parentIDi < consumer->nbInputs(); ++parentIDi) { - if (consumer->getOperator()->getNbConsumedData(parentIDi) < - consumer->getOperator()->getNbRequiredData(parentIDi)) { - computationOverForConsumer = false; - break; - } - } - if (computationOverForConsumer) { - computationOver.insert(consumer); - } - for (IOIndex_t outId = 0; outId < consumer->nbOutputs(); ++outId) { if (consumer->getOperator()->getNbProducedData(outId) > 0) { if (verbose) printf(" also producer\n"); @@ -197,8 +167,52 @@ void Aidge::SequentialScheduler::forward(bool frowardDims, bool verbose) { if (verbose) printf("*************\n"); } while (!consumers.empty()); + +} + +// TODO: handle multiple inputs/outputs +void Aidge::SequentialScheduler::forward(bool forwardDims, bool verbose) { + if (forwardDims) {mGraphView->forwardDims(); } + + // add each Producer Node. + std::set<std::shared_ptr<Node>> computationOver; + + mScheduling.clear(); + + this->generateScheduling(); + + // TODO: For loop on the list of node to run + // run sequencially every runnable consumers once + // TODO: handle memory allocation in scheduler + // TODO: optimize memory usage + for (const auto& runnable : mStaticSchedule) { + bool computationOverForConsumer = true; + for (IOIndex_t parentIDi = 0; parentIDi < runnable->nbInputs(); ++parentIDi) { + if (runnable->getOperator()->getNbConsumedData(parentIDi) < + runnable->getOperator()->getNbRequiredData(parentIDi)) { + computationOverForConsumer = false; + break; + } + } + if (computationOverForConsumer) { + computationOver.insert(runnable); + } + + if (verbose) + printf("run: %s\n", + (runnable->type() + "_" + std::to_string(reinterpret_cast<uintptr_t>(runnable.get()))).c_str()); + else + drawProgressBar(static_cast<float>(computationOver.size()) / static_cast<float>(mComputationNumber), 50, + (std::string("running ") + runnable->type() + "_" + + std::to_string(reinterpret_cast<uintptr_t>(runnable.get())))); + const auto tStart = std::chrono::high_resolution_clock::now(); + runnable->forward(); + const auto tEnd = std::chrono::high_resolution_clock::now(); + mScheduling.push_back(SchedulingElement(runnable, tStart, tEnd)); + } if (!verbose) drawProgressBar(1.0, 50, " "); printf("\n"); + } void Aidge::SequentialScheduler::saveSchedulingDiagram(const std::string& fileName) const { @@ -231,4 +245,4 @@ std::set<std::shared_ptr<Aidge::Node>> Aidge::SequentialScheduler::getConsumers( } return consumers; -} \ No newline at end of file +}