From 4c135b3823c073981cb76b3180255cd096482dc5 Mon Sep 17 00:00:00 2001 From: Mahder Gebremedhin Date: Thu, 29 Oct 2020 12:49:09 +0100 Subject: [PATCH] Update ParModAuto sources. - There are so many changes here. - Capability for monitoring and rescheduling added. - Use JSON instad of XML - updated compliation seetings. e.g. use GC_THREADS from the compilation command instead of defining it in the files. - many other fixes and changes. --- .../ParModelica/auto/Makefile.common | 8 +- .../ParModelica/auto/Makefile.in | 25 +- .../ParModelica/auto/Makefile.omdev.mingw | 34 +- .../ParModelica/auto/om_pm_interface.cpp | 134 ++++-- .../ParModelica/auto/om_pm_interface.hpp | 28 +- .../ParModelica/auto/om_pm_model.cpp | 415 ++++++++++++------ .../ParModelica/auto/om_pm_model.hpp | 30 +- .../auto/pm_cluster_dynamic_scheduler.hpp | 371 ++++++++-------- .../auto/pm_cluster_level_scheduler.hpp | 241 +++++++--- .../ParModelica/auto/pm_cluster_system.hpp | 174 ++++++-- .../ParModelica/auto/pm_clustering.hpp | 120 ++++- .../ParModelica/auto/pm_graph_dump.hpp | 8 +- .../ParModelica/auto/pm_graph_dump.inl | 33 -- .../ParModelica/auto/pm_posix_timer.cpp | 2 +- .../ParModelica/auto/pm_timer.hpp | 2 +- .../ParModelica/auto/pm_utility.hpp | 369 ++++++++-------- .../ParModelica/auto/pm_win_timer.cpp | 6 +- 17 files changed, 1279 insertions(+), 721 deletions(-) diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/Makefile.common b/OMCompiler/SimulationRuntime/ParModelica/auto/Makefile.common index 535d247b642..e7d8265c9c7 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/Makefile.common +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/Makefile.common @@ -8,8 +8,6 @@ om_pm_equation.cpp \ pm_utility.cpp \ om_pm_interface.cpp \ om_pm_model.cpp -# ParModelicaTaskGrapExt_rml.cpp -# ParModelicaTaskGrapExt_omc.cpp \ HDRS = *.hpp *.inl OBJS = $(SRCS:.cpp=.o) @@ -24,7 +22,7 @@ libParModelicaAuto.a: $(OBJS) $(AR_) $@ $(OBJS) .cpp.o: $(DPFILE) - $(CC) $(CPPFLAGS) $(INCDIRS) -c $< + $(CXX) $(CPPFLAGS) $(INCDIRS) -c $< test: test_task_graph.cpp libParModelicaAuto.a $(CXX) $(CPPFLAGS) -I. $(INCDIRS) test_task_graph.cpp -o gen_graph$(EXEEXT) libParModelicaAuto.a -L$(TBB_LIB) -ltbb @@ -34,6 +32,6 @@ clean : touch $(DPFILE) $(DPFILE) depend : $(HDRS) $(SRCS) - $(CC) $(DPFLAGS) $(CPPFLAGS) $(SRCS) > $(DPFILE) + $(CXX) $(DPFLAGS) $(CPPFLAGS) $(INCDIRS) $(SRCS) > $(DPFILE) -include $(DPFILE) \ No newline at end of file +include $(DPFILE) diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/Makefile.in b/OMCompiler/SimulationRuntime/ParModelica/auto/Makefile.in index 6b5d910c4db..4dd8910b907 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/Makefile.in +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/Makefile.in @@ -1,26 +1,45 @@ TOP_BUILDDIR = @OMBUILDDIR@ HOST_SHORT = @host_short@ +OMCOMPILER_ROOT = $(realpath ../../../) + OPENMODELICA_INC=$(TOP_BUILDDIR)/include/omc/c/ PARMODELICAAUTO_INC=$(OPENMODELICA_INC)/ParModelica/auto/ OPENMODELICA_LIB=$(TOP_BUILDDIR)/lib/$(HOST_SHORT)/omc OPENMODELICA_BIN=$(TOP_BUILDDIR)/bin/ BOOST_HOME = @BOOSTHOME@ -INCDIRS = -I"../../c" -I$(BOOST_HOME) -I"../pugixml-1.2/src/" +INCDIRS = -I"../../c" -I$(BOOST_HOME) -I$(OMCOMPILER_ROOT)/3rdParty/tbb/include -I$(OMCOMPILER_ROOT)/3rdParty/gc/include CC=@CC@ CXX=@CXX@ -CFLAGS=@CFLAGS@ $(INCDIRS) -CPPFLAGS= -O3 -Wall -fPIC +CFLAGS=@CFLAGS@ +CPPFLAGS= @CFLAGS@ -Wall -DGC_THREADS OS_SRCS = pm_posix_timer.cpp EXEEXT= DLLEXT=.so +ifeq ($(USE_LEVEL_SCHEDULER), 1) +CPPFLAGS += -DUSE_LEVEL_SCHEDULER +$(info ************ COMPILING FOR LEVEL SCHEDULER ************) +else ifeq ($(USE_FLOW_SCHEDULER), 1) +$(info ************ COMPILING FOR FLOW SCHEDULER ************) +CPPFLAGS += -DUSE_FLOW_SCHEDULER +endif + +ifeq ($(NUM_THREADS), ) +$(info ************ NUM THREADS NOT SET ************) +$(info ************ NUM THREADS NOT SET ************) +$(info ************ NUM THREADS NOT SET ************) +$(info ************ NUM THREADS NOT SET ************) +else +CPPFLAGS += -DNUM_THREADS=$(NUM_THREADS) +endif + all: transfer transfer: libParModelicaAuto.a diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/Makefile.omdev.mingw b/OMCompiler/SimulationRuntime/ParModelica/auto/Makefile.omdev.mingw index 203bdac2588..6a7d6d0aea9 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/Makefile.omdev.mingw +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/Makefile.omdev.mingw @@ -1,25 +1,43 @@ -TOP_BUILDDIR = ../../../build/ +OMBUILDDIR = $(realpath ../../../../)/build +OMCOMPILER_ROOT = $(realpath ../../../) -OPENMODELICA_INC=$(TOP_BUILDDIR)/include/omc/c/ +OPENMODELICA_INC=$(OMBUILDDIR)/include/omc/c/ PARMODELICAAUTO_INC=$(OPENMODELICA_INC)/ParModelica/auto/ -OPENMODELICA_LIB=$(TOP_BUILDDIR)/lib/omc/ -OPENMODELICA_BIN=$(TOP_BUILDDIR)/bin/ +OPENMODELICA_LIB=$(OMBUILDDIR)/lib/omc/ +OPENMODELICA_BIN=$(OMBUILDDIR)/bin/ -TBB_INC = $(OMC_TBB_INC) +TBB_INC = ../tbb/include TBB_LIB = $(OMC_TBB_LIB) BOOST_HOME = $(OMDEV)/lib/3rdParty/boost-1_49 -INCDIRS = -I"../../c" -I$(TBB_INC) -I$(BOOST_HOME) -I"../pugixml-1.2/src/" +INCDIRS = -I"../../c" -I$(BOOST_HOME) -I$(OMCOMPILER_ROOT)/3rdParty/tbb/include -I$(OMCOMPILER_ROOT)/3rdParty/gc/include CC=gcc CXX=g++ -CFLAGS= -O3 -Wall -CPPFLAGS= -O3 -Wall +CFLAGS= -O3 -Wall +CPPFLAGS= -std=c++11 -O3 -Wall -DGC_THREADS + OS_SRCS = pm_win_timer.cpp EXEEXT=.exe DLLEXT=.dll + +ifeq ($(USE_LEVEL_SCHEDULER), 1) +CPPFLAGS += -DUSE_LEVEL_SCHEDULER +$(info ************ COMPILING FOR LEVEL SCHEDULER ************) +else +$(info ************ COMPILING FOR FLOW SCHEDULER ************) +CPPFLAGS += -DUSE_FLOW_SCHEDULER +endif + +ifeq ($(NUM_THREADS), ) +$(info ************ NUM THREADS NOT SET. SETTIN TO 4 ************) +CPPFLAGS += -DNUM_THREADS=4 +else +CPPFLAGS += -DNUM_THREADS=$(NUM_THREADS) +endif + all: transfer transfer: libParModelicaAuto.a diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_interface.cpp b/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_interface.cpp index 650f2ecfe33..5ccfbb415d2 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_interface.cpp +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_interface.cpp @@ -46,69 +46,127 @@ extern "C" { using namespace openmodelica::parmodelica; typedef Equation::FunctionType FunctionType; -OMModel pm_om_model; +PMTimer seq_ode_timer; -void PM_Model_init(const char* model_name, DATA* data, threadData_t* threadData, FunctionType* ode_system) { - pm_om_model.initialize(model_name, data, threadData, ode_system); -} -void PM_functionInitialEquations(int size, DATA* data, threadData_t* threadData, FunctionType* functionInitialEquations_systems) { +void* PM_Model_create(const char* model_name, DATA* data, threadData_t* threadData) { + OMModel* pm_om_model = new OMModel(model_name); + pm_om_model->data = data; + pm_om_model->threadData = threadData; + return pm_om_model; +} - // pm_om_model.ini_system_funcs = functionInitialEquations_systems; - // pm_om_model.INI_scheduler.execute(); - pm_om_model.INI_scheduler.execution_timer.start_timer(); - for(int i = 0; i < size; ++i) - functionInitialEquations_systems[i](data, threadData); - pm_om_model.INI_scheduler.execution_timer.stop_timer(); +void PM_Model_load_ODE_system(void* v_model, FunctionType* ode_system_funcs) { + OMModel& model = *(static_cast(v_model)); + model.ode_system_funcs = ode_system_funcs; + model.load_ODE_system(); } -void PM_functionDAE(int size, DATA* data, threadData_t* threadData, FunctionType* functionDAE_systems) { +// void PM_functionInitialEquations(int size, FunctionType* functionInitialEquations_systems) { - // pm_om_model.dae_system_funcs = functionDAE_systems; - // pm_om_model.DAE_scheduler.execute(); + // // pm_om_model.ini_system_funcs = functionInitialEquations_systems; + // // pm_om_model.INI_scheduler.execute(); + // pm_om_model.INI_scheduler.execution_timer.start_timer(); + // for(int i = 0; i < size; ++i) + // functionInitialEquations_systems[i](data, threadData); + // pm_om_model.INI_scheduler.execution_timer.stop_timer(); - pm_om_model.DAE_scheduler.execution_timer.start_timer(); - for(int i = 0; i < size; ++i) - functionDAE_systems[i](data, threadData); - pm_om_model.DAE_scheduler.execution_timer.stop_timer(); +// } -} +// void PM_functionDAE(int size, FunctionType* functionDAE_systems) { + + // // pm_om_model.dae_system_funcs = functionDAE_systems; + // // pm_om_model.DAE_scheduler.execute(); + + // pm_om_model.DAE_scheduler.execution_timer.start_timer(); + // for(int i = 0; i < size; ++i) + // functionDAE_systems[i](data, threadData); + // pm_om_model.DAE_scheduler.execution_timer.stop_timer(); + +// } -void PM_functionODE(int size, DATA* data, threadData_t* threadData, FunctionType* functionODE_systems) { - pm_om_model.ODE_scheduler.execute(); +void PM_evaluate_ODE_system(void* v_model) { - // pm_om_model.ODE_scheduler.execution_timer.start_timer(); + OMModel& model = *(static_cast(v_model)); + model.ODE_scheduler.execute(); + + // pm_om_model.ODE_scheduler.execution_timer.start_timer(); // for(int i = 0; i < size; ++i) // functionODE_systems[i](data, threadData); - // pm_om_model.ODE_scheduler.execution_timer.stop_timer(); - + // pm_om_model.ODE_scheduler.execution_timer.stop_timer(); - // double step_cost = pm_om_model.ODE_scheduler.execution_timer.get_elapsed_time(); - // std::cout << step_cost << std::endl; - // pm_om_model.ODE_scheduler.execution_timer.reset_timer(); } -void PM_functionAlg(int size, DATA* data, threadData_t* threadData, FunctionType* functionAlg_systems) { +// void PM_functionAlg(int size, DATA* data, threadData_t* threadData, FunctionType* functionAlg_systems) { - pm_om_model.total_alg_time.start_timer(); + // pm_om_model.ALG_scheduler.execution_timer.start_timer(); - for(int i = 0; i < size; ++i) - functionAlg_systems[i](data, threadData); + // for(int i = 0; i < size; ++i) + // functionAlg_systems[i](data, threadData); + + // pm_om_model.ALG_scheduler.execution_timer.start_timer(); + +// } + +void seq_ode_timer_start() { + seq_ode_timer.start_timer(); +} - pm_om_model.total_alg_time.stop_timer(); +void seq_ode_timer_stop() { + seq_ode_timer.stop_timer(); +} + +void seq_ode_timer_reset() { + seq_ode_timer.reset_timer(); +} + +void seq_ode_timer_get_elapsed_time2() { + // return seq_ode_timer.get_elapsed_time(); + std::cerr << seq_ode_timer.get_elapsed_time(); +} +double seq_ode_timer_get_elapsed_time() { + return seq_ode_timer.get_elapsed_time(); } -void dump_times() { - utility::log("") << "Total INI: " << pm_om_model.INI_scheduler.execution_timer.get_elapsed_time() << std::endl; - utility::log("") << "Total DAE: " << pm_om_model.DAE_scheduler.execution_timer.get_elapsed_time() << std::endl; - utility::log("") << "Total ODE: " << pm_om_model.ODE_scheduler.execution_timer.get_elapsed_time() << std::endl; - utility::log("") << "Total ODE: " << pm_om_model.ODE_scheduler.clustering_timer.get_elapsed_time() << std::endl; - utility::log("") << "Total ALG: " << pm_om_model.total_alg_time.get_elapsed_time() << std::endl; +void dump_times(void* v_model) { + OMModel& model = *(static_cast(v_model)); + + // utility::log("") << "Total INI: " << model.INI_scheduler.execution_timer.get_elapsed_time() << std::endl; + // utility::log("") << "Total DAE: " << model.DAE_scheduler.execution_timer.get_elapsed_time() << std::endl; + // utility::log("") << "Total ALG: " << model.ALG_scheduler.execution_timer.get_elapsed_time() << std::endl; + + // double total = 0; + // for(unsigned int i = 0; i < model.ODE_scheduler.parallel_eval_costs.size(); ++i) { + // double c = model.ODE_scheduler.parallel_eval_costs[i]; + // total += c; + // utility::log("") << i+1 << ": " << c << " : " << total/(i+1) << std::endl; + // } + + // utility::log("") << "Total ODE added: " << total << std::endl; + // std::cout << model.ODE_scheduler.execution_timer.get_elapsed_time() << std::endl; + // std::cout << model.ODE_scheduler.total_evaluations << " : " << model.ODE_scheduler.total_parallel_cost << std::endl; +#ifdef USE_LEVEL_SCHEDULER + utility::log("") << "Using level scheduler" << std::endl; +#else + #ifdef USE_FLOW_SCHEDULER + utility::log("") << "Using flow scheduler" << std::endl; + #else + #error "please specify scheduler. See makefile" + #endif +#endif + utility::log("") << "Nr.of threads " << NUM_THREADS << std::endl; + utility::log("") << "Nr.of ODE evaluations: " << model.ODE_scheduler.total_evaluations << std::endl; + utility::log("") << "Nr.of profiling ODE Evaluations: " << model.ODE_scheduler.sequential_evaluations << std::endl; + // utility::log("") << "Total ODE evaluation time : " << model.ODE_scheduler.total_parallel_cost << std::endl; + utility::log("") << "Total ODE evaluation time : " << model.ODE_scheduler.execution_timer.get_elapsed_time() << std::endl; + utility::log("") << "Avg. ODE evaluation time : " << model.ODE_scheduler.execution_timer.get_elapsed_time()/model.ODE_scheduler.parallel_evaluations << std::endl; + utility::log("") << "Total ODE loading time: " << model.load_system_timer.get_elapsed_time() << std::endl; + utility::log("") << "Total ODE Clustering time: " << model.ODE_scheduler.clustering_timer.get_elapsed_time() << std::endl; } diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_interface.hpp b/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_interface.hpp index cf80d2a3804..0c711dad516 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_interface.hpp +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_interface.hpp @@ -39,7 +39,7 @@ Mahder.Gebremedhin@liu.se 2014-02-19 */ -#include +#include "simulation_data.h" #ifdef __cplusplus @@ -48,17 +48,31 @@ extern "C" { typedef void (*FunctionType)(DATA *, threadData_t*); -void PM_Model_init(const char* , DATA* , threadData_t*, FunctionType*); +void* PM_Model_create(const char* , DATA* , threadData_t*); -void PM_functionInitialEquations(int size, DATA* data, threadData_t* threadData, FunctionType*); +void PM_Model_load_ODE_system(void*, FunctionType*); -void PM_functionDAE(int size, DATA* data, threadData_t* threadData, FunctionType*); +// void PM_functionInitialEquations(int size, DATA* data, threadData_t* threadData, FunctionType*); -void PM_functionODE(int size, DATA* data, threadData_t* threadData, FunctionType*); +// void PM_functionDAE(int size, DATA* data, threadData_t* threadData, FunctionType*); -void PM_functionAlg(int size, DATA* data, threadData_t* threadData, FunctionType*); +void PM_evaluate_ODE_system(void*); -void dump_times(); +// void PM_functionAlg(int size, DATA* data, threadData_t* threadData, FunctionType*); + + +void seq_ode_timer_start(); + +void seq_ode_timer_stop(); + +void seq_ode_timer_reset(); + +void seq_ode_timer_get_elapsed_time2(); + +double seq_ode_timer_get_elapsed_time(); + + +void dump_times(void*); diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_model.cpp b/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_model.cpp index 01000879236..9b6d4dfdb90 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_model.cpp +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_model.cpp @@ -39,7 +39,10 @@ #include "om_pm_model.hpp" #include -#include +// #include + +#include "json.hpp" + namespace openmodelica { @@ -64,13 +67,19 @@ bool Equation::depends_on(const TaskNode& other_b) const { found_dep = utility::has_intersection(this->rhs.begin(),this->rhs.end(), other.lhs.begin(), other.lhs.end()); // Anti-dependency - if(!found_dep) + if(!found_dep) { found_dep = utility::has_intersection(this->lhs.begin(),this->lhs.end(), other.rhs.begin(), other.rhs.end()); + if(found_dep) + std::cout << "found anti-dep" << this->index << " and " << other.index << std::endl; + } // output-dependency - if(!found_dep) + if(!found_dep) { found_dep = utility::has_intersection(this->lhs.begin(),this->lhs.end(), other.lhs.begin(), other.lhs.end()); + if(found_dep) + std::cout << "found output-dep" << this->index << " and " << other.index << std::endl; + } return found_dep; } @@ -81,27 +90,30 @@ void Equation::execute() { } -OMModel::OMModel() : - INI_scheduler(INI_system), - DAE_scheduler(DAE_system), - ODE_scheduler(ODE_system) +OMModel::OMModel(const std::string& in_name) : + name(in_name) + , INI_system(name) + , INI_scheduler(INI_system) + , DAE_system(name) + , DAE_scheduler(DAE_system) + , ODE_system(name) + , ODE_scheduler(ODE_system) + , ALG_system(name) + , ALG_scheduler(ALG_system) { intialized = false; } -void OMModel::initialize(const char* model_name_, DATA* data_, threadData_t* threadData_, FunctionType* ode_system_) { +void OMModel::load_ODE_system() { if(intialized) return; - model_name = model_name_; - data = data_; - threadData = threadData_; - ode_system_funcs = ode_system_; - - load_from_xml(ODE_system, "ode-equations", ode_system_funcs); + load_system_timer.start_timer(); + load_from_json(ODE_system, "ode-equations", ode_system_funcs); + load_system_timer.stop_timer(); // ODE_system.construct_graph(); // ODE_scheduler.set_up_executor(ode_system_funcs, data); // ODE_scheduler.schedule(4); @@ -112,179 +124,322 @@ void OMModel::initialize(const char* model_name_, DATA* data_, threadData_t* thr } -void load_equation(Equation& current_node, pugi::xml_node& xml_equ) { +// void load_equation(Equation& current_node, pugi::xml_node& xml_equ) { - pugi::xml_node eq_type = xml_equ.first_child(); - current_node.type = eq_type.name(); + // pugi::xml_node eq_type = xml_equ.first_child(); + // current_node.type = eq_type.name(); - if( std::strcmp(eq_type.name(),"assign") == 0) { + // if( std::strcmp(eq_type.name(),"assign") == 0) { - pugi::xml_node current = eq_type.first_child(); + // pugi::xml_node current = eq_type.first_child(); - while(std::strcmp(current.name(),"defines") == 0) { - current_node.lhs.insert(current.attribute("name").value()); - current = current.next_sibling(); - } + // while(std::strcmp(current.name(),"defines") == 0) { + // current_node.lhs.insert(current.attribute("name").value()); + // current = current.next_sibling(); + // } - while(std::strcmp(current.name(),"depends") == 0) { - current_node.rhs.insert(current.attribute("name").value()); - current = current.next_sibling(); - } + // while(std::strcmp(current.name(),"depends") == 0) { + // current_node.rhs.insert(current.attribute("name").value()); + // current = current.next_sibling(); + // } - current_node.cost = 1; - } - else if( std::strcmp(eq_type.name(),"statement") == 0) { + // current_node.cost = 1; + // } + // else if( std::strcmp(eq_type.name(),"statement") == 0) { - pugi::xml_node current = eq_type.first_child(); + // pugi::xml_node current = eq_type.first_child(); - while(std::strcmp(current.name(),"defines") == 0) { - current_node.lhs.insert(current.attribute("name").value()); - current = current.next_sibling(); - } + // while(std::strcmp(current.name(),"defines") == 0) { + // current_node.lhs.insert(current.attribute("name").value()); + // current = current.next_sibling(); + // } - while(std::strcmp(current.name(),"depends") == 0) { - current_node.rhs.insert(current.attribute("name").value()); - current = current.next_sibling(); - } + // while(std::strcmp(current.name(),"depends") == 0) { + // current_node.rhs.insert(current.attribute("name").value()); + // current = current.next_sibling(); + // } - current_node.cost = 1; - } - else if( std::strcmp(eq_type.name(),"when") == 0) { + // current_node.cost = 1; + // } + // else if( std::strcmp(eq_type.name(),"when") == 0) { - pugi::xml_node current = eq_type.first_child(); - current_node.rhs.insert(current.child_value()); - current = current.next_sibling(); + // pugi::xml_node current = eq_type.first_child(); + // current_node.rhs.insert(current.child_value()); + // current = current.next_sibling(); - while(std::strcmp(current.name(),"defines") == 0) { - current_node.lhs.insert(current.attribute("name").value()); - current = current.next_sibling(); - } + // while(std::strcmp(current.name(),"defines") == 0) { + // current_node.lhs.insert(current.attribute("name").value()); + // current = current.next_sibling(); + // } - while(std::strcmp(current.name(),"depends") == 0) { - current_node.rhs.insert(current.attribute("name").value()); - current = current.next_sibling(); - } + // while(std::strcmp(current.name(),"depends") == 0) { + // current_node.rhs.insert(current.attribute("name").value()); + // current = current.next_sibling(); + // } - current_node.cost = 2; - } + // current_node.cost = 2; + // } - else if( std::strcmp(eq_type.name(),"linear") == 0) { + // else if( std::strcmp(eq_type.name(),"linear") == 0) { - pugi::xml_node current = eq_type.first_child(); + // pugi::xml_node current = eq_type.first_child(); - int ls_size = 0; - while(std::strcmp(current.name(),"defines") == 0) { - current_node.lhs.insert(current.attribute("name").value()); - current = current.next_sibling(); - ++ls_size; - } + // int ls_size = 0; + // while(std::strcmp(current.name(),"defines") == 0) { + // current_node.lhs.insert(current.attribute("name").value()); + // current = current.next_sibling(); + // ++ls_size; + // } - while(std::strcmp(current.name(),"depends") == 0) { - current_node.rhs.insert(current.attribute("name").value()); - current = current.next_sibling(); - } + // while(std::strcmp(current.name(),"depends") == 0) { + // current_node.rhs.insert(current.attribute("name").value()); + // current = current.next_sibling(); + // } - current_node.cost = ls_size; - utility::warning() << current_node.index << ": Linear equations not fully handled yet: " << ls_size << newl; - } + // current_node.cost = ls_size; + // utility::warning() << current_node.index << ": Linear equations not fully handled yet: " << ls_size << newl; + // } - else if( std::strcmp(eq_type.name(),"nonlinear") == 0) { + // else if( std::strcmp(eq_type.name(),"nonlinear") == 0) { - pugi::xml_node current = eq_type.first_child(); + // pugi::xml_node current = eq_type.first_child(); - int nls_size = 0; - while(std::strcmp(current.name(),"defines") == 0) { - current_node.lhs.insert(current.attribute("name").value()); - current = current.next_sibling(); - ++nls_size; - } + // int nls_size = 0; + // while(std::strcmp(current.name(),"defines") == 0) { + // current_node.lhs.insert(current.attribute("name").value()); + // current = current.next_sibling(); + // ++nls_size; + // } - while(std::strcmp(current.name(),"depends") == 0) { - current_node.rhs.insert(current.attribute("name").value()); - current = current.next_sibling(); - } + // while(std::strcmp(current.name(),"depends") == 0) { + // current_node.rhs.insert(current.attribute("name").value()); + // current = current.next_sibling(); + // } - current_node.cost = nls_size; - utility::warning() << current_node.index << ": Non linear equations not fully handled yet: " << nls_size << newl; - } + // current_node.cost = nls_size; + // utility::warning() << current_node.index << ": Non linear equations not fully handled yet: " << nls_size << newl; + // } - else if( std::strcmp(eq_type.name(),"mixed") == 0) { + // else if( std::strcmp(eq_type.name(),"mixed") == 0) { - int mix_size = eq_type.attribute("size").as_int(); + // int mix_size = eq_type.attribute("size").as_int(); - pugi::xml_node current = eq_type.first_child(); + // pugi::xml_node current = eq_type.first_child(); - while(std::strcmp(current.name(),"defines") == 0) { - current_node.lhs.insert(current.attribute("name").value()); - current = current.next_sibling(); - } + // while(std::strcmp(current.name(),"defines") == 0) { + // current_node.lhs.insert(current.attribute("name").value()); + // current = current.next_sibling(); + // } - current_node.cost = mix_size; + // current_node.cost = mix_size; + + // for(int count = 0; count < mix_size; ++count) { + // xml_equ = xml_equ.next_sibling(); + // Equation mix_eq_node; + // load_node(mix_eq_node, xml_equ); + // current_node.lhs.insert(mix_eq_node.lhs.begin(), mix_eq_node.lhs.end()); + // current_node.rhs.insert(mix_eq_node.rhs.begin(), mix_eq_node.rhs.end()); + // } + + // utility::warning() << current_node.index << ": Mixed equations not fully handled yet: " << mix_size << newl; + // } + + // else { + // current_node.cost = 1; + // utility::error() << current_node.index << ": Unknown Equation type." << eq_type.name() << newl; + // } + + +// } + +// void OMModel::load_from_xml(TaskSystemT& task_system, const std::string& eq_to_read, FunctionType* function_system) { + + // std::string xml_file = model_name + "_tasks.xml"; + // utility::log("") << "Loading " << xml_file << std::endl; + + // pugi::xml_document doc; + // if(!doc.load_file(xml_file.c_str())) { + // std::cerr << "Error loading XML file '" << xml_file << "'." << std::endl; + // exit(1); + // } + + + // pugi::xml_node xml_equs = doc.child("tasksystemdump").child(eq_to_read.c_str()); + + // long node_count = 0; - for(int count = 0; count < mix_size; ++count) { - xml_equ = xml_equ.next_sibling(); - Equation mix_eq_node; - load_node(mix_eq_node, xml_equ); - current_node.lhs.insert(mix_eq_node.lhs.begin(), mix_eq_node.lhs.end()); - current_node.rhs.insert(mix_eq_node.rhs.begin(), mix_eq_node.rhs.end()); - } - utility::warning() << current_node.index << ": Mixed equations not fully handled yet: " << mix_size << newl; + // for (pugi::xml_node xml_equ = xml_equs.first_child(); xml_equ; ) + // { + + // Equation current_node; + // pugi::xml_attribute index = xml_equ.first_attribute(); + // current_node.index = index.as_int(); + + // // Copy the pointers to the needed info from the Model + // // to each equation node. + // current_node.data = this->data; + // current_node.threadData = this->threadData; + // current_node.function_system = function_system; + + + // load_equation(current_node, xml_equ); + // ++node_count; + + // task_system.add_node(current_node); + + // xml_equ = xml_equ.next_sibling(); + // } + + + // utility::log() << "Number of tasks = " << node_count << newl; + + +// } + + +inline void check_tag(int index, const std::string& tag) { + if (tag == "dummy" + or tag == "assign" + or tag == "residual" + or tag == "algorithm" + or tag == "container") + return; + else { + std::cerr << index << " : with unknown tag : " << tag << std::endl; + exit(1); } +} +inline void check_container_dispaly(int index, const std::string& disp) { + if (disp == "linear" + or disp == "non-linear") + return; else { - current_node.cost = 1; - utility::error() << current_node.index << ": Unknown Equation type." << eq_type.name() << newl; + std::cerr << index << " : container with unknown disp : " << disp << std::endl; + exit(1); } +} +void OMModel::load_from_json(TaskSystemT& task_system, const std::string& eq_to_read, FunctionType* function_system) { + std::string json_file = this->name + "_ode.json"; + // utility::log("") << "Loading " << json_file << std::endl; -} + std::set complex_eq_lhs; + std::set complex_eq_rhs; + int current_parent = -1; + std::ifstream f_s(json_file); + nlohmann::json jmodel_info; -void OMModel::load_from_xml(TaskSystemT& task_system, const std::string& eq_to_read, FunctionType* function_system) { + jmodel_info << f_s; - std::string xml_file = model_name + "_tasks.xml"; - utility::log("") << "Loading " << xml_file << std::endl; + // std::cout << std::setw(4) << jmodel_info["equations"][] << std::endl; + long node_count = 0; + for(auto eq : jmodel_info[eq_to_read]) { - pugi::xml_document doc; - if(!doc.load_file(xml_file.c_str())) { - std::cerr << "Error loading XML file '" << xml_file << "'." << std::endl; - exit(1); - } + int index = eq["eqIndex"]; + // skip the 'dummy' node in OpenModelica generated JSON file. + if (index == 0) { + continue; + } + // So that we know what we can handle so far. + check_tag(index, eq["tag"]); - pugi::xml_node xml_equs = doc.child("tasksystemdump").child(eq_to_read.c_str()); + /*an equation with no parent and is not a container(system). create a new node for it.*/ + if(eq["parent"] == nullptr && eq["tag"] != "container") { + Equation current_node; + current_node.index = index; - long node_count = 0; + // Copy the pointers to the needed info from the Model + // to each equation node. + current_node.data = this->data; + current_node.threadData = this->threadData; + current_node.function_system = function_system; + + for(auto def : eq["defines"]) { + current_node.lhs.insert(def.get()); + } + for(auto use : eq["uses"]) + current_node.rhs.insert(use.get()); + + ++node_count; + task_system.add_node(current_node); + } + /*an equation with parent and is not a complex system. collect references from it to pass + to its parent.*/ + else if(eq["parent"] != nullptr && eq["tag"] != "container") { + if(current_parent == -1) + current_parent = eq["parent"]; + else if (eq["parent"] != current_parent) { + std::cerr << "current parent " << current_parent <<" and equation parent " << eq["parent"] << " don't add up. something is fishy" << std::endl; + exit(1); + } + + // std::cout << "Collecting from : "<< index << " for : " << eq["parent"] << std::endl; + + for(auto def : eq["defines"]) { + complex_eq_lhs.insert(def.get()); + } + for(auto use : eq["uses"]) + complex_eq_rhs.insert(use.get()); + } + /*an equation with no parent and is a complex system. create a new node for it + using the collected rhs and lsh references from its children.*/ + else if(eq["parent"] == nullptr && eq["tag"] == "container") { - for (pugi::xml_node xml_equ = xml_equs.first_child(); xml_equ; ) - { + check_container_dispaly(index,eq["display"]); - Equation current_node; - pugi::xml_attribute index = xml_equ.first_attribute(); - current_node.index = index.as_int(); + Equation current_node; + current_node.index = index; - // Copy the pointers to the needed info from the Model - // to each equation node. - current_node.data = this->data; - current_node.threadData = this->threadData; - current_node.function_system = function_system; + // Copy the pointers to the needed info from the Model + // to each equation node. + current_node.data = this->data; + current_node.threadData = this->threadData; + current_node.function_system = function_system; + current_node.lhs = complex_eq_lhs; + complex_eq_lhs.clear(); + for(auto def : eq["defines"]) { + current_node.lhs.insert(def.get()); + } - load_equation(current_node, xml_equ); - ++node_count; + // std::cout << "Equation: " << index << " defines : "<< std::endl; + // for(auto def : current_node.lhs) + // std::cout << def << ", "; + // std::cout << std::endl; - task_system.add_node(current_node); - xml_equ = xml_equ.next_sibling(); - } + current_node.rhs = complex_eq_rhs; + complex_eq_rhs.clear(); + for(auto use : eq["uses"]) { + current_node.rhs.insert(use.get()); + } + + // std::cout << "Equation: " << index << " uses : "<< std::endl; + // for(auto use : current_node.rhs) + // std::cout << use << ", "; + // std::cout << std::endl; + current_parent = -1; - utility::log() << "Number of tasks = " << node_count << newl; + ++node_count; + task_system.add_node(current_node); + + } + else { + std::cerr << "Equation type not yet handled : " << index << std::endl; + std::cerr << eq << std::endl; + exit(1); + } + } + std::cout << "Number of tasks = " << node_count << newl; } diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_model.hpp b/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_model.hpp index 836b8420ea5..fb0450325f4 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_model.hpp +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/om_pm_model.hpp @@ -40,12 +40,12 @@ #include -#include "pm_task_system.hpp" +// #include "pm_task_system.hpp" #include "pm_cluster_level_scheduler.hpp" #include "pm_cluster_dynamic_scheduler.hpp" -#include "pm_level_scheduler.hpp" -#include "pm_dynamic_scheduler.hpp" +// #include "pm_level_scheduler.hpp" +// #include "pm_dynamic_scheduler.hpp" #include "pm_timer.hpp" @@ -92,22 +92,30 @@ class OMModel // typedef LevelSchedulerThreadOblivious SchedulerT; // typedef DynamicScheduler SchedulerT; // typedef TaskSystem TaskSystemT; - +#ifdef USE_LEVEL_SCHEDULER typedef StepLevels SchedulerT; - // typedef ClusterDynamicScheduler SchedulerT; +#else + #ifdef USE_FLOW_SCHEDULER + typedef ClusterDynamicScheduler SchedulerT; + #else + #error "please specify scheduler. See makefile" + #endif +#endif typedef TaskSystem_v2 TaskSystemT; -private: - std::string model_name; +public: + std::string name; bool intialized; DATA* data; threadData_t* threadData; public: - OMModel(); - void initialize(const char* , DATA* , threadData_t* , FunctionType*); + OMModel(const std::string&); + void load_ODE_system(); + + PMTimer load_system_timer; FunctionType* ini_system_funcs; TaskSystemT INI_system; @@ -121,10 +129,12 @@ class OMModel TaskSystemT ODE_system; SchedulerT ODE_scheduler; - PMTimer total_alg_time; + FunctionType alg_system_funcs; TaskSystemT ALG_system; + SchedulerT ALG_scheduler; void load_from_xml(TaskSystemT&, const std::string&, FunctionType*); + void load_from_json(TaskSystemT&, const std::string&, FunctionType*); }; diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_cluster_dynamic_scheduler.hpp b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_cluster_dynamic_scheduler.hpp index ff2866af16a..8e1afd8e65a 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_cluster_dynamic_scheduler.hpp +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_cluster_dynamic_scheduler.hpp @@ -1,180 +1,191 @@ -#pragma once -#ifndef id776A2949_F8C6_41C1_8E5205C1984621C1 -#define id776A2949_F8C6_41C1_8E5205C1984621C1 - -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-CurrentYear, Linköping University, - * Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 - * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S - * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from Linköping University, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS - * OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - - -/* - Mahder.Gebremedhin@liu.se 2014-03-06 -*/ - -#include -#include - -#include "pm_clustering.hpp" - - -namespace openmodelica { -namespace parmodelica { - -template -struct ClusterLauncher { - typedef TaskSystem_v2 TaskSystemType; - typedef typename TaskSystemType::ClusterType ClusterType; -private: - ClusterType& clust; - -public: - ClusterLauncher(ClusterType& c) - : clust(c) - {} - - void operator()( tbb::flow::continue_msg ) const { - clust.execute(); - } -}; - -template -class ClusterDynamicScheduler { -public: - typedef TaskSystem_v2 TaskSystemType; - - typedef typename TaskSystemType::GraphType GraphType; - typedef typename TaskSystemType::ClusterType ClusterType; - typedef typename TaskSystemType::ClusterIdType ClusterIdType; - - typedef typename TaskType::FunctionType FunctionType; - -private: - tbb::task_scheduler_init tbb_system; - - tbb::flow::graph dynamic_graph; - tbb::flow::broadcast_node flow_root; - - bool flow_graph_created; - - - std::map* > cluster_flow_id_map; - -public: - PMTimer execution_timer; - PMTimer clustering_timer; - TaskSystemType& task_system; - - ClusterDynamicScheduler(TaskSystemType& task_system) - : tbb_system() - , flow_root(dynamic_graph) - , flow_graph_created(false) - , task_system(task_system) - { - } - - void schedule() { - clustering_timer.start_timer(); - cluster_merge_common::apply(task_system); - cluster_merge_common::dump_graph(task_system); - construct_flow_graph(); - clustering_timer.stop_timer(); - } - - void construct_flow_graph() - { - - using namespace tbb; - GraphType& sys_graph = task_system.sys_graph; - ClusterIdType& root_node_id = task_system.root_node_id; - - typename GraphType::vertex_iterator vert_iter, vert_end; - boost::tie(vert_iter, vert_end) = vertices(sys_graph); - - /*! skip the root node. */ - ++vert_iter; - for ( ; vert_iter != vert_end; ++vert_iter) { - ClusterIdType& curr_clust_id = *vert_iter; - ClusterType& curr_clust = sys_graph[curr_clust_id]; - // std::cout << "adding " << curr_b_node.index << std::endl; - - /*! create new flow node for tbb. */ - flow::continue_node* curr_f_node = - new flow::continue_node(dynamic_graph, - ClusterLauncher(curr_clust)); - - /*! create a maping. we use it to add edges from this node to its children later. */ - cluster_flow_id_map.insert(std::make_pair(curr_clust_id,curr_f_node)); - - /*! Iterate through all parents of the current node and add edges.*/ - typename GraphType::inv_adjacency_iterator par_iter, par_end; - boost::tie(par_iter, par_end) = inv_adjacent_vertices( curr_clust_id, sys_graph ); - for(; par_iter != par_end; ++par_iter) { - const ClusterIdType& curr_parent_id = *par_iter; - // ClusterType& curr_parent = sys_graph[curr_parent_id]; - /*! the parent is the root in the task_graph. So here connect it to - the root of the flow graph*/ - if(curr_parent_id == root_node_id) { - flow::make_edge(flow_root, *curr_f_node); - // std::cout << " edge to root " << std::endl; - } - else { - flow::make_edge(*(cluster_flow_id_map.at(curr_parent_id)), *curr_f_node); - // std::cout << " edge to " << sys_graph[*par_iter].index << std::endl; - } - } - } - - flow_graph_created = true; - } - - - void execute() { - - if(!flow_graph_created) { - construct_flow_graph(); - } - - execution_timer.start_timer(); - flow_root.try_put( tbb::flow::continue_msg() ); - dynamic_graph.wait_for_all(); - execution_timer.stop_timer(); - } - -}; - - - -} // parmodelica -} // openmodelica - - - - -#endif // header +#pragma once +#ifndef id776A2949_F8C6_41C1_8E5205C1984621C1 +#define id776A2949_F8C6_41C1_8E5205C1984621C1 + +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS + * OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + + +/* + Mahder.Gebremedhin@liu.se 2014-03-06 +*/ + +#include +#include + +#include "pm_clustering.hpp" + + +namespace openmodelica { +namespace parmodelica { + +template +struct ClusterLauncher { + typedef TaskSystem_v2 TaskSystemType; + typedef typename TaskSystemType::ClusterType ClusterType; +private: + ClusterType& clust; + +public: + ClusterLauncher(ClusterType& c) + : clust(c) + {} + + void operator()( tbb::flow::continue_msg ) const { + clust.execute(); + } +}; + +template +class ClusterDynamicScheduler { +public: + typedef TaskSystem_v2 TaskSystemType; + + typedef typename TaskSystemType::GraphType GraphType; + typedef typename TaskSystemType::ClusterType ClusterType; + typedef typename TaskSystemType::ClusterIdType ClusterIdType; + + typedef typename TaskType::FunctionType FunctionType; + +private: + tbb::task_scheduler_init tbb_system; + + tbb::flow::graph dynamic_graph; + tbb::flow::broadcast_node flow_root; + + bool flow_graph_created; + + + std::map* > cluster_flow_id_map; + +public: + PMTimer execution_timer; + PMTimer clustering_timer; + TaskSystemType& task_system; + + int sequential_evaluations; + int total_evaluations; + int parallel_evaluations; + + ClusterDynamicScheduler(TaskSystemType& task_system) + : tbb_system(NUM_THREADS) + , flow_root(dynamic_graph) + , flow_graph_created(false) + , task_system(task_system) + { + sequential_evaluations = 0; + parallel_evaluations =0; + total_evaluations = 0; + } + + void schedule() { + // task_system.dump_graphml("original"); + clustering_timer.start_timer(); + // cluster_merge_common::apply(task_system); + // cluster_merge_common::dump_graph(task_system); + construct_flow_graph(); + clustering_timer.stop_timer(); + } + + void construct_flow_graph() + { + + using namespace tbb; + GraphType& sys_graph = task_system.sys_graph; + ClusterIdType& root_node_id = task_system.root_node_id; + + typename GraphType::vertex_iterator vert_iter, vert_end; + boost::tie(vert_iter, vert_end) = vertices(sys_graph); + + /*! skip the root node. */ + ++vert_iter; + for ( ; vert_iter != vert_end; ++vert_iter) { + ClusterIdType& curr_clust_id = *vert_iter; + ClusterType& curr_clust = sys_graph[curr_clust_id]; + // std::cout << "adding " << curr_b_node.index << std::endl; + + /*! create new flow node for tbb. */ + flow::continue_node* curr_f_node = + new flow::continue_node(dynamic_graph, + ClusterLauncher(curr_clust)); + + /*! create a maping. we use it to add edges from this node to its children later. */ + cluster_flow_id_map.insert(std::make_pair(curr_clust_id,curr_f_node)); + + /*! Iterate through all parents of the current node and add edges.*/ + typename GraphType::inv_adjacency_iterator par_iter, par_end; + boost::tie(par_iter, par_end) = inv_adjacent_vertices( curr_clust_id, sys_graph ); + for(; par_iter != par_end; ++par_iter) { + const ClusterIdType& curr_parent_id = *par_iter; + // ClusterType& curr_parent = sys_graph[curr_parent_id]; + /*! the parent is the root in the task_graph. So here connect it to + the root of the flow graph*/ + if(curr_parent_id == root_node_id) { + flow::make_edge(flow_root, *curr_f_node); + // std::cout << " edge to root " << std::endl; + } + else { + flow::make_edge(*(cluster_flow_id_map.at(curr_parent_id)), *curr_f_node); + // std::cout << " edge to " << sys_graph[*par_iter].index << std::endl; + } + } + } + + flow_graph_created = true; + } + + + void execute() { + + if(!flow_graph_created) { + schedule(); + } + + execution_timer.start_timer(); + flow_root.try_put( tbb::flow::continue_msg() ); + dynamic_graph.wait_for_all(); + execution_timer.stop_timer(); + + total_evaluations++; + parallel_evaluations++; + } + +}; + + + +} // parmodelica +} // openmodelica + + + + +#endif // header diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_cluster_level_scheduler.hpp b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_cluster_level_scheduler.hpp index cb1523dbec8..2dea4d8d7fb 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_cluster_level_scheduler.hpp +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_cluster_level_scheduler.hpp @@ -38,8 +38,14 @@ Mahder.Gebremedhin@liu.se 2014-03-13 */ +#include "gc.h" + #include #include +#include + +// #include +// #include #include "pm_clustering.hpp" @@ -61,14 +67,36 @@ struct TBBConcurrentStepExecutor { typedef typename ClusterLevels::value_type SameLevelClusterIdsType; typedef typename SameLevelClusterIdsType::iterator ClusteIdIter; + private: GraphType& sys_graph; + std::set& knownthreads; public: - TBBConcurrentStepExecutor(GraphType& g) : sys_graph(g) {} + TBBConcurrentStepExecutor(GraphType& g, std::set& k) : sys_graph(g) , knownthreads(k) {} void operator()( tbb::blocked_range& range ) const { + // pid_t id; + // /* Register thread to bohem GC if it is not registered already*/ + // if(!GC_thread_is_registered()) { + // id = syscall(SYS_gettid); + // fprintf(stderr,"Found unregisterd thread = %d \n", id); + + // struct GC_stack_base sb; + // memset (&sb, 0, sizeof(sb)); + // GC_get_stack_base(&sb); + // GC_register_my_thread (&sb); + // // std::cerr << "New Theread registerd = " << GC_thread_is_registered() << std::endl; + // } + // else { + // id = syscall(SYS_gettid); + // if(!knownthreads.count(id)) { + // fprintf(stderr,"parmod registerd thread = %d \n", id); + // knownthreads.insert(id); + // } + // } + for(ClusteIdIter clustid_iter = range.begin(); clustid_iter != range.end(); ++clustid_iter) { ClusterIdType& curr_clust_id = *clustid_iter; ClusterType& curr_clust = sys_graph[curr_clust_id]; @@ -83,7 +111,7 @@ struct TBBConcurrentStepExecutor { template step_executor; + std::set knownthreads; + + int total_evaluations; + int parallel_evaluations; + int sequential_evaluations; + + double par_avg_at_last_sch; + double par_current_avg; + double total_parallel_cost; + bool has_run_parallel; public: + std::string name; + PMTimer execution_timer; PMTimer clustering_timer; - // PMTimer extra_timer; + PMTimer step_timer; + + std::vector parallel_eval_costs; + StepLevels(TaskSystemType& ts) : - task_system(ts) - , tbb_system(4) - , step_executor(task_system.sys_graph) + task_system_org(ts) + , task_system("invalid") // implement a constrctor with no parameters and remove this + , tbb_system(NUM_THREADS) + , step_executor(task_system.sys_graph, knownthreads) { + GC_allow_register_threads(); + // GC_use_threads_discovery(); + profiled = false; - schedule_valid = false; - } + schedule_available = false; - void estimate_speedup() { + total_evaluations = 0; + parallel_evaluations = 0; + sequential_evaluations = 0; - if(task_system.levels_valid == false) - task_system.update_node_levels(); + total_parallel_cost = 0; + par_avg_at_last_sch = 0; + has_run_parallel = false; - GraphType& sys_graph = task_system.sys_graph; + } - double total_level_scheduler_cost = 0; - double total_system_cost = 0; - typename ClusterLevels::iterator level_iter = task_system.clusters_by_level.begin(); - /*! Skip the first level. Which contains only the root node and some invlaidated clusters.*/ - ++level_iter; - int level_number = 1; - for( ;level_iter != task_system.clusters_by_level.end(); ++level_iter, ++level_number) { - SameLevelClusterIdsType& current_level = *level_iter; + bool avg_needs_reschedule() { - cluster_cost_comparator_by_id cccbi(sys_graph); - std::sort(current_level.begin(), current_level.end(), cccbi); - total_level_scheduler_cost += sys_graph[current_level.front()].cost; + double diff = std::abs(par_avg_at_last_sch - par_current_avg); + double change = diff/par_avg_at_last_sch; - total_system_cost += current_level.level_cost; + if(change > 0.5) { + // std::cout << "Reschedule needed P: " << par_avg_at_last_sch << " :C: " << par_current_avg << std::endl; + return true; } - utility::log("") << "total_system_cost: " << total_system_cost << std::endl; - utility::log("") << "total_level_scheduler_cost: " << total_level_scheduler_cost << std::endl; - utility::log("") << "speedup: " << total_system_cost/total_level_scheduler_cost << std::endl; + return false; + } + + bool reschedule_needed() { + if(!this->schedule_available) + return true; + + if(this->avg_needs_reschedule()) + return true; + + return false; } - void schedule() { + void clear_schedule() { + task_system = task_system_org; + + profiled = false; + schedule_available = false; - if(schedule_valid) - return; + } + + void execute_and_schedule() { + clear_schedule(); + profile_execute(); + schedule(); + par_avg_at_last_sch = par_current_avg; + } + + void schedule() { clustering_timer.start_timer(); if(task_system.levels_valid == false) task_system.update_node_levels(); - task_system.dump_graphml("original"); - - clustetring1::apply(task_system); - clustetring1::dump_graph(task_system); + // clustetring1::apply(task_system); + // clustetring1::dump_graph(task_system, std::to_string(this->total_evaluations)); clustetring2::apply(task_system); - clustetring2::dump_graph(task_system); + // clustetring2::dump_graph(task_system, std::to_string(this->total_evaluations)); clustetring3::apply(task_system); clustetring3::dump_graph(task_system); @@ -180,28 +244,32 @@ class StepLevels : clustetring5::apply(task_system); clustetring5::dump_graph(task_system); - schedule_valid = true; + schedule_available = true; task_system.levels_valid = false; + task_system.update_node_levels(); estimate_speedup(); clustering_timer.stop_timer(); + + // task_system_org.dump_graphml("original"); + + } void execute() { - if(!this->profiled) - return profile_execute(); - - execution_timer.start_timer(); - // extra_timer.start_timer(); - - // GraphType& sys_graph = task_system.sys_graph; + if(this->reschedule_needed()) + return execute_and_schedule(); + // paranoia if(task_system.levels_valid == false) - task_system.update_node_levels(); + exit(1); + + execution_timer.start_timer(); + step_timer.start_timer(); typename ClusterLevels::iterator level_iter = task_system.clusters_by_level.begin(); /*! Skip the first level. Which contains only the root node */ @@ -229,37 +297,92 @@ class StepLevels : } execution_timer.stop_timer(); - // extra_timer.stop_timer(); - // double step_cost = extra_timer.get_elapsed_time(); - // std::cout << "E: " << step_cost << std::endl; - // extra_timer.reset_timer(); + step_timer.stop_timer(); + + ++this->total_evaluations; + ++this->parallel_evaluations; + + + // if(total_evaluations%100 == 0) { + double step_cost = step_timer.get_elapsed_time(); + parallel_eval_costs.push_back(step_cost); + total_parallel_cost += step_cost; + par_current_avg = total_parallel_cost/this->parallel_evaluations; + // std::cout << total_evaluations << " : " << parallel_evaluations << " : " << step_cost << " : " << par_current_avg << std::endl; + // std::cout << "P" << " : " << total_evaluations << " : " << step_cost << " : "<< par_current_avg << std::endl; + step_timer.reset_timer(); + // } + + if(!has_run_parallel) { + par_avg_at_last_sch = par_current_avg; + has_run_parallel = true; + } } void profile_execute() { - execution_timer.start_timer(); + // if(this->total_evaluations == 0) + // std::cout << "Type" << " : " << "Eval" << " : " << "Eval_cost" << " : "<< "Curr_Par_Avg" << " : " << "Prev_Sch_Avg"<< std::endl; GraphType& sys_graph = task_system.sys_graph; typename GraphType::vertex_iterator vert_iter, vert_end; boost::tie(vert_iter, vert_end) = vertices(sys_graph); + + execution_timer.start_timer(); + step_timer.start_timer(); /*! skip the root node. */ ++vert_iter; for ( ; vert_iter != vert_end; ++vert_iter) { sys_graph[*vert_iter].profile_execute(); } + ++this->total_evaluations; + ++this->sequential_evaluations; + step_timer.stop_timer(); execution_timer.stop_timer(); - // double step_cost = execution_timer.get_elapsed_time(); - // std::cout << "P: " << step_cost << std::endl; - // execution_timer.reset_timer(); + + double step_cost = step_timer.get_elapsed_time(); + // utility::log("") << "Profiled on step :" << this->total_evaluations << " cost: " << step_cost << std::endl; + std::cout << "S" << " : " << this->total_evaluations << " : " << step_cost << " : " << par_current_avg << " : " << par_avg_at_last_sch << std::endl; + step_timer.reset_timer(); + + + // task_system.dump_graphml("profiled_" + std::to_string(this->total_evaluations)); this->profiled = true; - this->schedule_valid = false; - schedule(); + } + + void estimate_speedup() { + + if(task_system.levels_valid == false) + task_system.update_node_levels(); + + GraphType& sys_graph = task_system.sys_graph; + + double total_level_scheduler_cost = 0; + double total_system_cost = 0; + typename ClusterLevels::iterator level_iter = task_system.clusters_by_level.begin(); + /*! Skip the first level. Which contains only the root node and some invlaidated clusters.*/ + ++level_iter; + int level_number = 1; + for( ;level_iter != task_system.clusters_by_level.end(); ++level_iter, ++level_number) { + SameLevelClusterIdsType& current_level = *level_iter; + + cluster_cost_comparator_by_id cccbi(sys_graph); + // sort in decreasing order + std::sort(current_level.rbegin(), current_level.rend(), cccbi); + total_level_scheduler_cost += sys_graph[current_level.front()].cost; + + total_system_cost += current_level.total_level_cost; + } + + // utility::log("") << "Total_system_cost: " << total_system_cost << std::endl; + // utility::log("") << "Total_level_scheduler_cost: " << total_level_scheduler_cost << std::endl; + // utility::log("") << "Ideal speedup: " << total_system_cost/total_level_scheduler_cost << std::endl; } @@ -270,13 +393,13 @@ class StepLevels : //template //using LevelScheduler = StepLevels; template struct LevelScheduler : StepLevels {}; diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_cluster_system.hpp b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_cluster_system.hpp index 9a5e41f01d1..29485a8e5c9 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_cluster_system.hpp +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_cluster_system.hpp @@ -42,10 +42,14 @@ #include +#include #include +#include + #include #include +#include #include "pm_utility.hpp" #include "pm_timer.hpp" @@ -55,19 +59,19 @@ namespace openmodelica { namespace parmodelica { -// struct TaskNode { - // TaskNode() : - // level(0) - // , cost(0) - // {}; +struct TaskNode { + TaskNode() : + level(0) + , cost(0) + {}; - // long task_id; - // int level; - // double cost; + long task_id; + int level; + double cost; - // virtual bool depends_on(const TaskNode&) const = 0; - // // virtual void execute() const = 0; -// }; + virtual bool depends_on(const TaskNode&) const = 0; + virtual void execute() = 0; +}; @@ -109,6 +113,7 @@ struct TaskCluster : void clear_cluster() { this->clear(); this->cost = 0; + this->index_list = "$"; } bool depends_on(const TaskCluster& other) const { @@ -126,8 +131,7 @@ struct TaskCluster : } - void execute() - { + void execute() { iterator t_iter; for(t_iter = this->begin(); t_iter != this->end(); ++t_iter) { t_iter->execute(); @@ -185,9 +189,9 @@ struct cluster_cost_comparator_by_id // if(lhs_degree == rhs_degree) { // } - return lhs_degree > rhs_degree; + return lhs_degree < rhs_degree; } - return lhs_cost > rhs_cost; + return lhs_cost < rhs_cost; } }; @@ -198,10 +202,10 @@ struct SameLevelClusterIds : { typedef T ClusterIdType; - double level_cost; + double total_level_cost; SameLevelClusterIds() : - level_cost(0) + total_level_cost(0) {} }; @@ -209,7 +213,7 @@ struct SameLevelClusterIds : template -class TaskSystem_v2 : boost::noncopyable { +class TaskSystem_v2 { public: typedef T TaskType; @@ -229,34 +233,87 @@ class TaskSystem_v2 : boost::noncopyable { typedef typename GraphType::in_edge_iterator in_edge_iterator; typedef typename GraphType::out_edge_iterator out_edge_iterator; - typedef std::list > ClusterLevels; + typedef std::vector > ClusterLevels; private: long node_count; public: + std::string name; - std::set active_nodes; ClusterLevels clusters_by_level; bool levels_valid; double total_cost; + GraphType sys_graph; ClusterIdType root_node_id; - TaskSystem_v2() + TaskSystem_v2(const std::string& in_name) { + name = in_name; levels_valid = false; node_count = 0; total_cost = 0; + + // add a new cluster for root node. root_node_id = boost::add_vertex(sys_graph); + // add an empty task to the root node. TaskType& root_node = sys_graph[root_node_id].add_task(TaskType()); root_node.task_id = -1; } + TaskSystem_v2(const TaskSystem_v2& other) + { + this->name = other.name; + this->node_count = other.node_count; + + this->clusters_by_level = other.clusters_by_level; + + this->levels_valid = other.levels_valid; + this->total_cost = other.total_cost; + + this->sys_graph = other.sys_graph; + // typedef std::map IndexMap; + // IndexMap mapIndex; + // boost::associative_property_map propmapIndex(mapIndex); + + // int i=0; + // BGL_FORALL_VERTICES_T(v, other.sys_graph, GraphType) + // { + // boost::put(propmapIndex, v, i++); + // } + // boost::copy_graph(other.sys_graph,this->sys_graph, boost::vertex_index_map( propmapIndex )); + // for (typename IndexMap::iterator p = mapIndex.begin(); p != mapIndex.end(); ++p) { + // std::cout << p->first << " -> " << p->second << std::endl; + // } + + vertex_iterator vert_iter, vert_end; + boost::tie(vert_iter, vert_end) = vertices(this->sys_graph); + this->root_node_id = *vert_iter; + } + + TaskSystem_v2& operator=(const TaskSystem_v2& other) { + + this->name = other.name; + this->node_count = other.node_count; + + this->clusters_by_level = other.clusters_by_level; + + this->levels_valid = other.levels_valid; + this->total_cost = other.total_cost; + + this->sys_graph = other.sys_graph; + + vertex_iterator vert_iter, vert_end; + boost::tie(vert_iter, vert_end) = vertices(this->sys_graph); + this->root_node_id = *vert_iter; + + return *this; + } + TaskType& add_node(const TaskType& task) { ClusterIdType new_clust_id = boost::add_vertex(sys_graph); - active_nodes.insert(new_clust_id); ClusterType& new_clust = sys_graph[new_clust_id]; @@ -391,7 +448,7 @@ class TaskSystem_v2 : boost::noncopyable { typename ClusterLevels::iterator level_iter = clusters_by_level.begin(); for( ;level_iter != clusters_by_level.end(); ++level_iter, ++level_number) { SameLevelClusterIdsType& current_level = *level_iter; - std::cout << "Level " << level_number << " : " << current_level.level_cost << " : "; + std::cout << "Level " << level_number << " : " << current_level.total_level_cost << " : "; typename SameLevelClusterIdsType::iterator clustid_iter = current_level.begin(); for( ;clustid_iter != current_level.end(); ++clustid_iter) { @@ -419,10 +476,8 @@ class TaskSystem_v2 : boost::noncopyable { void update_node_levels() { - typedef typename ClusterLevels::value_type SameLevelClusterIdsType; - - clusters_by_level.clear(); + /* compute the level of each node*/ long critical_path = 0; vertex_iterator vert_iter, vert_end; boost::tie(vert_iter, vert_end) = vertices(sys_graph); @@ -448,22 +503,8 @@ class TaskSystem_v2 : boost::noncopyable { } - clusters_by_level.resize(critical_path + 1); - - typename ClusterLevels::iterator level_iter; - boost::tie(vert_iter, vert_end) = vertices(sys_graph); - for ( ; vert_iter != vert_end; ++vert_iter) { - const ClusterIdType& curr_clust_id = *vert_iter; - ClusterType& curr_clust = sys_graph[curr_clust_id]; - - - level_iter = clusters_by_level.begin(); - std::advance(level_iter, curr_clust.level); - level_iter->push_back(curr_clust_id); - level_iter->level_cost += curr_clust.cost; - } - + // Check the levels are correct. Paranoia! boost::tie(vert_iter, vert_end) = vertices(sys_graph); /*! skip the root node. */ ++vert_iter; @@ -495,6 +536,27 @@ class TaskSystem_v2 : boost::noncopyable { } + // create alist of nodes per level + // Collect nodes of the same level in to a vector and add it to the list of levels + clusters_by_level.clear(); + clusters_by_level.resize(critical_path + 1); + typedef typename ClusterLevels::value_type SameLevelClusterIdsType; + + typename ClusterLevels::iterator level_iter; + boost::tie(vert_iter, vert_end) = vertices(sys_graph); + for ( ; vert_iter != vert_end; ++vert_iter) { + const ClusterIdType& curr_clust_id = *vert_iter; + ClusterType& curr_clust = sys_graph[curr_clust_id]; + + // find the entry in the level list for the current node. its level defines where it goes + SameLevelClusterIdsType& my_level = clusters_by_level[curr_clust.level]; + // std::advance(level_iter, curr_clust.level); + + // Add it to the vector of nodes of that level. + my_level.push_back(curr_clust_id); + my_level.total_level_cost += curr_clust.cost; + } + this->levels_valid = true; @@ -502,7 +564,35 @@ class TaskSystem_v2 : boost::noncopyable { void load_from_xml(const std::string& file_name, const std::string& eq_to_read); - void dump_graphml(const std::string& filename); + + void dump_graphml(const std::string& suffix) { + + if(levels_valid == false) + update_node_levels(); + + + std::string out_filename = this->name + "_" + suffix + ".graphml"; + std::ofstream outfileml(out_filename.c_str()); + boost::dynamic_properties dp; + dp.property("index", boost::get(&ClusterType::index_list, sys_graph)); + dp.property("level", boost::get(&ClusterType::level, sys_graph)); + dp.property("cost", boost::get(&ClusterType::cost, sys_graph)); + + + /*! Now we have listS as vertex container. listS doesn't have VertexIndexMap + created by default. So we create one for it here. */ + typedef std::map ClustIndexMap; + ClustIndexMap clust_map_index; + boost::associative_property_map clust_prop_map_index(clust_map_index); + + size_t node_count = 0; + BGL_FORALL_VERTICES_T(clust_id, sys_graph, GraphType) + { + boost::put(clust_prop_map_index, clust_id, node_count++); + } + + write_graphml(outfileml, sys_graph, clust_prop_map_index, dp, true); + } }; diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_clustering.hpp b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_clustering.hpp index d6230de86db..fd8a21490ba 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_clustering.hpp +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_clustering.hpp @@ -40,6 +40,7 @@ #include "pm_cluster_system.hpp" +#include namespace openmodelica { namespace parmodelica { @@ -252,7 +253,7 @@ struct cluster_none { } template - static void dump_graph(TaskSystemType& task_system) { + static void dump_graph(TaskSystemType& task_system, std::string suffix = "") { /*! No op*/ } @@ -270,8 +271,8 @@ struct cluster_merge_level_for_cost { } template - static void dump_graph(TaskSystemType& task_system) { - task_system.dump_graphml(cluster_merge_level_for_cost::name()); + static void dump_graph(TaskSystemType& task_system, std::string suffix = "") { + task_system.dump_graphml(cluster_merge_level_for_cost::name()+ "_" + suffix); } template @@ -287,7 +288,7 @@ struct cluster_merge_level_for_cost { ClusterLevels& clusters_by_level = task_system.clusters_by_level; GraphType& sys_graph = task_system.sys_graph; - int nr_of_clusters = 4; + int nr_of_clusters = 8; if(task_system.levels_valid == false) task_system.update_node_levels(); @@ -301,10 +302,11 @@ struct cluster_merge_level_for_cost { SameLevelClusterIdsType& current_level = *level_iter; /*!Sort the level by cost so that we can pick the nodes that fits the gap easily*/ + // sort in decreasing order cluster_cost_comparator_by_id cccbi(sys_graph); - std::sort(current_level.begin(), current_level.end(), cccbi); + std::sort(current_level.rbegin(), current_level.rend(), cccbi); - double target_cost = current_level.level_cost/nr_of_clusters; + double target_cost = current_level.total_level_cost/nr_of_clusters; if(target_cost < sys_graph[current_level.front()].cost) { target_cost = sys_graph[current_level.front()].cost; } @@ -350,7 +352,7 @@ struct cluster_merge_level_for_cost { typename SameLevelClusterIdsType::iterator remaining_iter, smallest_clust_iter; while(clustid_iter != current_level.end()) { - smallest_clust_iter = std::min_element(current_level.begin(), current_level.begin() + nr_of_clusters); + smallest_clust_iter = std::min_element(current_level.begin(), current_level.begin() + nr_of_clusters, cccbi); task_system.concat_same_level_clusters(*smallest_clust_iter, *clustid_iter); clustid_iter = current_level.erase(clustid_iter); } @@ -363,6 +365,89 @@ struct cluster_merge_level_for_cost { }; +struct cluster_merge_level_for_bins { + static std::string name() { + return "cluster_merge_level_for_bins"; + } + + template + static void dump_graph(TaskSystemType& task_system, std::string suffix = "") { + task_system.dump_graphml(cluster_merge_level_for_bins::name()+ "_" + suffix); + } + + template + static void apply(TaskSystemType& task_system) { + + typedef typename TaskSystemType::GraphType GraphType; + typedef typename TaskSystemType::ClusterLevels ClusterLevels; + // typedef typename TaskSystemType::ClusterType ClusterType; + // typedef typename TaskSystemType::ClusterIdType ClusterIdType; + + typedef typename ClusterLevels::value_type SameLevelClusterIdsType; + + ClusterLevels& clusters_by_level = task_system.clusters_by_level; + GraphType& sys_graph = task_system.sys_graph; + + int nr_of_clusters = NUM_THREADS*2; + + if(task_system.levels_valid == false) + task_system.update_node_levels(); + + + typename ClusterLevels::iterator level_iter = clusters_by_level.begin(); + /*! Skip the first level. Which contains only the root node and some invlaidated clusters.*/ + ++level_iter; + int level_number = 1; + for( ;level_iter != clusters_by_level.end(); ++level_iter, ++level_number) { + SameLevelClusterIdsType& current_level = *level_iter; + + if(current_level.size() <= nr_of_clusters) + continue; + + /*!Sort the level by cost so that we can pick the nodes that fits the gap easily*/ + // sort in decreasing order + cluster_cost_comparator_by_id cccbi(sys_graph); + std::sort(current_level.rbegin(), current_level.rend(), cccbi); + + // std::cout << "current level {"; + // for(auto& c: current_level) + // std::cout << sys_graph[c].cost << ","; + // std::cout << "}" << std::endl; + + typename SameLevelClusterIdsType::iterator smallest_clust_iter, clustid_iter, end_of_accepted; + + // Accept the first n clusters as merged tasks + end_of_accepted = current_level.begin(); + std::advance(end_of_accepted, nr_of_clusters); + // std::cout << "will start at: " << std::distance(current_level.begin(), end_of_accepted) << ": "<< sys_graph[*end_of_accepted].cost << std::endl; + + // iterate through the rest and merge with the smallest currently + clustid_iter = end_of_accepted; + while(clustid_iter != current_level.end()) { + // std::cout << "current level {"; + // for(auto& c: current_level) + // std::cout << sys_graph[c].cost << ","; + // std::cout << "}" << std::endl; + + smallest_clust_iter = std::min_element(current_level.begin(), end_of_accepted, cccbi); + // std::cout << "smallest is " << std::distance(current_level.begin(), smallest_clust_iter) << ": "<< sys_graph[*smallest_clust_iter].cost << std::endl; + task_system.concat_same_level_clusters(*smallest_clust_iter, *clustid_iter); + clustid_iter = current_level.erase(clustid_iter); + } + + // std::cout << "current level {"; + // for(auto& c: current_level) + // std::cout << sys_graph[c].cost << ","; + // std::cout << "}" << std::endl; + + } + + task_system.levels_valid = false; + + } + +}; + struct cluster_merge_common { static std::string name() { @@ -370,8 +455,8 @@ struct cluster_merge_common { } template - static void dump_graph(TaskSystemType& task_system) { - task_system.dump_graphml(cluster_merge_common::name()); + static void dump_graph(TaskSystemType& task_system, std::string suffix = "") { + task_system.dump_graphml(cluster_merge_common::name()+ "_" + suffix); } template @@ -382,7 +467,7 @@ struct cluster_merge_common { typedef typename TaskSystemType::ClusterType ClusterType; typedef typename TaskSystemType::ClusterIdType ClusterIdType; typedef typename TaskSystemType::adjacency_iterator adjacency_iterator; - typedef typename TaskSystemType::out_edge_iterator out_edge_iterator; + // typedef typename TaskSystemType::out_edge_iterator out_edge_iterator; GraphType& sys_graph = task_system.sys_graph; @@ -403,8 +488,9 @@ struct cluster_merge_common { child_ids.push_back(curr_child_id); } + // sort in decreasing order cluster_cost_comparator_by_id cccbi(sys_graph); - std::sort(child_ids.begin(), child_ids.end(), cccbi); + std::sort(child_ids.rbegin(), child_ids.rend(), cccbi); typename std::vector::iterator id_iter = child_ids.begin(); for ( ; id_iter != child_ids.end(); ++id_iter) { @@ -500,8 +586,8 @@ struct cluster_merge_single_parent { } template - static void dump_graph(TaskSystemType& task_system) { - task_system.dump_graphml(cluster_merge_single_parent::name()); + static void dump_graph(TaskSystemType& task_system, std::string suffix = "") { + task_system.dump_graphml(cluster_merge_single_parent::name()+ "_" + suffix); } template @@ -561,8 +647,8 @@ struct cluster_merge_level_parents { } template - static void dump_graph(TaskSystemType& task_system) { - task_system.dump_graphml(cluster_merge_level_parents::name()); + static void dump_graph(TaskSystemType& task_system, std::string suffix = "") { + task_system.dump_graphml(cluster_merge_level_parents::name()+ "_" + suffix); } template @@ -648,8 +734,8 @@ struct cluster_merge_connected_for_cost { } template - static void dump_graph(TaskSystemType& task_system) { - task_system.dump_graphml(cluster_merge_connected_for_cost::name()); + static void dump_graph(TaskSystemType& task_system, std::string suffix = "") { + task_system.dump_graphml(cluster_merge_connected_for_cost::name()+ "_" + suffix); } template diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_graph_dump.hpp b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_graph_dump.hpp index adb5e9de1e6..d81b140b43e 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_graph_dump.hpp +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_graph_dump.hpp @@ -44,11 +44,11 @@ namespace openmodelica { namespace parmodelica { -template -void dump_graphml(const TaskSystem& task_system, const std::string& filename); +// template +// void dump_graphml(const TaskSystem& task_system, const std::string& filename); -template -void dump_graphviz(const TaskSystem& task_system, const std::string& filename); +// template +// void dump_graphviz(const TaskSystem& task_system, const std::string& filename); diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_graph_dump.inl b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_graph_dump.inl index 54fcc589717..d4ef0649356 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_graph_dump.inl +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_graph_dump.inl @@ -73,39 +73,6 @@ void dump_graphviz(const TaskSystem& task_system, const std::string& } -template -void TaskSystem_v2::dump_graphml(const std::string& filename) { - - if(levels_valid == false) - update_node_levels(); - - - std::string out_filename = filename + ".graphml"; - std::ofstream outfileml(out_filename.c_str()); - boost::dynamic_properties dp; - dp.property("index", boost::get(&ClusterType::index_list, sys_graph)); - dp.property("level", boost::get(&ClusterType::level, sys_graph)); - dp.property("cost", boost::get(&ClusterType::cost, sys_graph)); - - - - /*! Now we have listS as vertex container. listS doesn't have VertexIndexMap - created by default. So we create one for it here. */ - typedef std::map ClustIndexMap; - ClustIndexMap clust_map_index; - boost::associative_property_map clust_prop_map_index(clust_map_index); - - size_t node_count = 0; - BGL_FORALL_VERTICES_T(clust_id, sys_graph, GraphType) - { - boost::put(clust_prop_map_index, clust_id, node_count++); - } - - write_graphml(outfileml, sys_graph, clust_prop_map_index, dp, true); - -} - - } // openmodelica } // parmodelica \ No newline at end of file diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_posix_timer.cpp b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_posix_timer.cpp index 006d4a07c5f..44c6f5bbbf0 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_posix_timer.cpp +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_posix_timer.cpp @@ -58,7 +58,7 @@ void PMTimer::reset_timer(){ } double PMTimer::get_elapsed_time(){ - return boost::chrono::nanoseconds(total_time).count() / 1000000000.0; + return boost::chrono::nanoseconds(total_time).count() / 1000000.0; } } // parmodelica diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_timer.hpp b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_timer.hpp index 938f804bd31..e0fb5ea6b7f 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_timer.hpp +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_timer.hpp @@ -56,7 +56,7 @@ class PMTimer { PMStopWatch timer; LARGE_INTEGER total_time; LARGE_INTEGER frequency; - double LI_to_secs(LARGE_INTEGER &LI) ; + double LI_to_milli_secs(LARGE_INTEGER &LI) ; public: PMTimer(); void start_timer(); diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_utility.hpp b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_utility.hpp index dabc1a99c1e..6663259f4ae 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_utility.hpp +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_utility.hpp @@ -1,181 +1,190 @@ -#pragma once -#ifndef id8073C0EB_D490_45E7_9F4AE20BF9C28736 -#define id8073C0EB_D490_45E7_9F4AE20BF9C28736 - -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-CurrentYear, Linköping University, - * Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 - * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S - * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from Linköping University, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS - * OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - - -/* - Mahder.Gebremedhin@liu.se 2014-02-10 -*/ - - -#include -#include -#include -#include -#include - - -#ifdef _MSC_VER -#define NOMINMAX -#endif - -#define newl "\n" - - -namespace openmodelica { -namespace parmodelica { - -namespace utility { - - -extern std::ostringstream log_stream; -std::ostream& log(const char* pref); -std::ostream& log(); - -extern std::ostringstream warning_stream; -std::ostream& warning(const char* pref); -std::ostream& warning(); - - -extern std::ostringstream error_stream; -std::ostream& error(const char* pref); -std::ostream& error(); - - - -template -bool -has_intersection(InputIterator1 first1, InputIterator1 last1, - InputIterator2 first2, InputIterator2 last2) -{ - for(; first1 != last1; ++first1) { - std::set::iterator loc = std::find(first2, last2, (*first1)); - if(loc != last2) { - return true; - } - } - - return false; -} - -/* Slow. Use has_intersection instead. */ -template -bool -set_find_anyof(const SetType& InSet1, const SetType& InSet2) { - - for(typename SetType::const_iterator iter = InSet1.begin(); iter != InSet1.end(); ++iter) { - typename SetType::const_iterator loc = std::find(InSet2.begin(), InSet2.end(), (*iter)); - if(loc != InSet2.end()) { - return true; - } - } - - return false; - -} - - - - -template -class pm_vector { -protected: - std::vector int_vector; - -public: - pm_vector() { }; - pm_vector(int i, T p) : int_vector(i, p) { }; - - typedef typename std::vector::value_type value_type; - - typedef typename std::vector::iterator iterator; - typedef typename std::vector::const_iterator const_iterator; - - typedef typename std::vector::reference reference; - typedef typename std::vector::const_reference const_reference; - - typedef typename std::vector::size_type size_type; - - std::vector& get_vector() { return int_vector; }; - - size_type size() const { return int_vector.size(); } - size_type capacity() const { return int_vector.capacity(); } - bool empty() const { return int_vector.empty(); } - - void resize (size_type n, value_type val = value_type()) { int_vector.resize(n,val); } - - iterator begin() { return int_vector.begin(); } - const_iterator begin() const { return int_vector.begin(); } - - iterator end() { return int_vector.end(); } - const_iterator end() const { return int_vector.end(); } - - void push_back(const_reference p) { int_vector.push_back(p); }; - void push_front(const_reference p) { int_vector.push_front(p); }; - - reference back() { return int_vector.back(); } - const_reference back() const { return int_vector.back(); } - - reference front() { return int_vector.front(); } - const_reference front() const { return int_vector.front(); } - - - template - void insert(iterator pos, InputIterator first, InputIterator last) - { return int_vector.insert(pos, first, last); } - - iterator insert(iterator pos, const T& val) { return int_vector.insert(pos,val); } - iterator erase(iterator pos) { return int_vector.erase(pos); } - - void clear() { int_vector.clear(); } - - reference operator[](const size_type index) { return int_vector[index]; } - const_reference operator[](const size_type index) const { return int_vector[index]; } - - reference at(const size_type index) { return int_vector[index]; } - const_reference at(const size_type index) const { return int_vector[index]; } - -}; - - - - - -} // utility -} // parmodelica -} // openmodelica - - - +#pragma once +#ifndef id8073C0EB_D490_45E7_9F4AE20BF9C28736 +#define id8073C0EB_D490_45E7_9F4AE20BF9C28736 + +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS + * OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + + +/* + Mahder.Gebremedhin@liu.se 2014-02-10 +*/ + + +#include +#include +#include +#include +#include + + +#ifdef _MSC_VER +#define NOMINMAX +#endif + +#define newl "\n" + + +namespace openmodelica { +namespace parmodelica { + +namespace utility { + + +extern std::ostringstream log_stream; +std::ostream& log(const char* pref); +std::ostream& log(); + +extern std::ostringstream warning_stream; +std::ostream& warning(const char* pref); +std::ostream& warning(); + + +extern std::ostringstream error_stream; +std::ostream& error(const char* pref); +std::ostream& error(); + + + +template +bool +has_intersection(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2) +{ + for(; first1 != last1; ++first1) { + std::set::iterator loc = std::find(first2, last2, (*first1)); + if(loc != last2) { + return true; + } + } + + return false; +} + +/* Slow. Use has_intersection instead. */ +template +bool +set_find_anyof(const SetType& InSet1, const SetType& InSet2) { + + for(typename SetType::const_iterator iter = InSet1.begin(); iter != InSet1.end(); ++iter) { + typename SetType::const_iterator loc = std::find(InSet2.begin(), InSet2.end(), (*iter)); + if(loc != InSet2.end()) { + return true; + } + } + + return false; + +} + + + + +template +class pm_vector { +protected: + std::vector int_vector; + +public: + pm_vector() { }; + pm_vector(int i, T p) : int_vector(i, p) { }; + + typedef typename std::vector::value_type value_type; + + typedef typename std::vector::iterator iterator; + typedef typename std::vector::const_iterator const_iterator; + + typedef typename std::vector::reverse_iterator reverse_iterator; + typedef typename std::vector::const_reverse_iterator const_reverse_iterator; + + typedef typename std::vector::reference reference; + typedef typename std::vector::const_reference const_reference; + + typedef typename std::vector::size_type size_type; + + std::vector& get_vector() { return int_vector; }; + + size_type size() const { return int_vector.size(); } + size_type capacity() const { return int_vector.capacity(); } + bool empty() const { return int_vector.empty(); } + + void resize (size_type n, value_type val = value_type()) { int_vector.resize(n,val); } + + iterator begin() { return int_vector.begin(); } + const_iterator begin() const { return int_vector.begin(); } + + iterator end() { return int_vector.end(); } + const_iterator end() const { return int_vector.end(); } + + reverse_iterator rbegin() { return int_vector.rbegin(); } + const_reverse_iterator rbegin() const { return int_vector.rbegin(); } + + reverse_iterator rend() { return int_vector.rend(); } + const_reverse_iterator rend() const { return int_vector.rend(); } + + void push_back(const_reference p) { int_vector.push_back(p); }; + void push_front(const_reference p) { int_vector.push_front(p); }; + + reference back() { return int_vector.back(); } + const_reference back() const { return int_vector.back(); } + + reference front() { return int_vector.front(); } + const_reference front() const { return int_vector.front(); } + + + template + void insert(iterator pos, InputIterator first, InputIterator last) + { return int_vector.insert(pos, first, last); } + + iterator insert(iterator pos, const T& val) { return int_vector.insert(pos,val); } + iterator erase(iterator pos) { return int_vector.erase(pos); } + + void clear() { int_vector.clear(); } + + reference operator[](const size_type index) { return int_vector[index]; } + const_reference operator[](const size_type index) const { return int_vector[index]; } + + reference at(const size_type index) { return int_vector[index]; } + const_reference at(const size_type index) const { return int_vector[index]; } + +}; + + + + + +} // utility +} // parmodelica +} // openmodelica + + + #endif // header \ No newline at end of file diff --git a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_win_timer.cpp b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_win_timer.cpp index df60ce745eb..4d86e6300fc 100644 --- a/OMCompiler/SimulationRuntime/ParModelica/auto/pm_win_timer.cpp +++ b/OMCompiler/SimulationRuntime/ParModelica/auto/pm_win_timer.cpp @@ -43,8 +43,8 @@ namespace openmodelica { namespace parmodelica { -double PMTimer::LI_to_secs(LARGE_INTEGER &LI) { - return ((double)LI.QuadPart /(double)frequency.QuadPart) ; +double PMTimer::LI_to_milli_secs(LARGE_INTEGER &LI) { + return (((double)LI.QuadPart*1000) /(double)frequency.QuadPart) ; } PMTimer::PMTimer(){ @@ -70,7 +70,7 @@ void PMTimer::reset_timer(){ } double PMTimer::get_elapsed_time(){ - return LI_to_secs(total_time) ; + return LI_to_milli_secs(total_time) ; } } // parmodelica