diff --git a/CMakeLists.txt b/CMakeLists.txt index 67ad9304bc3e682a9436fb52306b3ca8120c1c4b..b764086c8e974dc53aadd345cdd287918d599afb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,9 +52,9 @@ target_include_directories(${module_name} ) # PYTHON BINDING -generate_python_binding(${project} ${module_name}) - if (PYBIND) + generate_python_binding(${project} ${module_name}) + # Handles Python + pybind11 headers dependencies target_link_libraries(${module_name} PUBLIC @@ -66,22 +66,12 @@ endif() target_compile_features(${module_name} PRIVATE cxx_std_14) - -if(WERROR) - target_compile_options(${module_name} PRIVATE +target_compile_options(${module_name} PRIVATE $<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>: - -Wall -Wextra -fPIC -Wold-style-cast -Winline -pedantic -Werror=narrowing -Wshadow -Werror>) - target_compile_options(${module_name} PRIVATE + -Wall -Wextra -Wold-style-cast -Winline -pedantic -Werror=narrowing -Wshadow $<$<BOOL:${WERROR}>:-Werror>>) +target_compile_options(${module_name} PRIVATE $<$<CXX_COMPILER_ID:MSVC>: /W4>) -else() - target_compile_options(${module_name} PRIVATE - $<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>: - -Wall -Wextra -fPIC -Wold-style-cast -Winline -pedantic -Werror=narrowing -Wshadow -Wpedantic>) - target_compile_options(${module_name} PRIVATE - $<$<CXX_COMPILER_ID:MSVC>: - /W4>) -endif() if(CMAKE_COMPILER_IS_GNUCXX AND COVERAGE) append_coverage_compiler_flags() diff --git a/cmake/PybindModuleCreation.cmake b/cmake/PybindModuleCreation.cmake index 18f4abc38e2537c3f4d949f08772a57b90758cb0..8030c1a8639e4b7ae0c5fb865e928a4260c6ae7d 100644 --- a/cmake/PybindModuleCreation.cmake +++ b/cmake/PybindModuleCreation.cmake @@ -1,23 +1,21 @@ -function(generate_python_binding name target_to_bind) - if (PYBIND) - add_definitions(-DPYBIND) - Include(FetchContent) +function(generate_python_binding name target_to_bind) + add_definitions(-DPYBIND) + Include(FetchContent) - FetchContent_Declare( - PyBind11 - GIT_REPOSITORY https://github.com/pybind/pybind11.git - GIT_TAG v2.10.4 # or a later release - ) + FetchContent_Declare( + PyBind11 + GIT_REPOSITORY https://github.com/pybind/pybind11.git + GIT_TAG v2.10.4 # or a later release + ) - # Use the New FindPython mode, recommanded. Requires CMake 3.15+ - find_package(Python COMPONENTS Interpreter Development) - FetchContent_MakeAvailable(PyBind11) + # Use the New FindPython mode, recommanded. Requires CMake 3.15+ + find_package(Python COMPONENTS Interpreter Development) + FetchContent_MakeAvailable(PyBind11) - message(STATUS "Creating binding for module ${name}") - file(GLOB_RECURSE pybind_src_files "python_binding/*.cpp") + message(STATUS "Creating binding for module ${name}") + file(GLOB_RECURSE pybind_src_files "python_binding/*.cpp") - pybind11_add_module(${name} MODULE ${pybind_src_files} "NO_EXTRAS") # NO EXTRA recquired for pip install - target_include_directories(${name} PUBLIC "python_binding") - target_link_libraries(${name} PUBLIC ${target_to_bind}) - endif() + pybind11_add_module(${name} MODULE ${pybind_src_files} "NO_EXTRAS") # NO EXTRA recquired for pip install + target_include_directories(${name} PUBLIC "python_binding") + target_link_libraries(${name} PUBLIC ${target_to_bind}) endfunction() diff --git a/include/aidge/aidge.hpp b/include/aidge/aidge.hpp index ff6601c487ea97294019a12ba899d251b08077e7..91386b9e5025bf348aafd6815484bee40441ace0 100644 --- a/include/aidge/aidge.hpp +++ b/include/aidge/aidge.hpp @@ -34,7 +34,7 @@ #include "aidge/operator/FC.hpp" #include "aidge/operator/GenericOperator.hpp" #include "aidge/operator/Matmul.hpp" -#include "aidge/operator/MetaOperator.hpp" +//#include "aidge/operator/MetaOperator.hpp" #include "aidge/operator/Operator.hpp" #include "aidge/operator/Producer.hpp" #include "aidge/operator/ReLU.hpp" 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 585096bebfb7dea6f491d550c841a20c4a9d532e..0289b92b8d26794930f2f392f143a6dc572a3762 100644 --- a/include/aidge/operator/Operator.hpp +++ b/include/aidge/operator/Operator.hpp @@ -86,6 +86,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 +}