00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __adevs_par_simulator_h_
00021 #define __adevs_par_simulator_h_
00022 #include "adevs_abstract_simulator.h"
00023 #include "adevs_msg_manager.h"
00024 #include "adevs_lp.h"
00025 #include "adevs_lp_graph.h"
00026 #include <cassert>
00027 #include <cstdlib>
00028 #include <iostream>
00029 #include <vector>
00030
00031 namespace adevs
00032 {
00033
00052 template <class X> class ParSimulator:
00053 public AbstractSimulator<X>
00054 {
00055 public:
00061 ParSimulator(Devs<X>* model, MessageManager<X>* msg_manager = NULL);
00068 ParSimulator(Devs<X>* model, LpGraph& g, MessageManager<X>* msg_manager = NULL);
00070 double nextEventTime();
00076 void execUntil(double stop_time);
00082 ~ParSimulator();
00083 private:
00084 LogicalProcess<X>** lp;
00085 int lp_count;
00086 MessageManager<X>* msg_manager;
00087 void init(Devs<X>* model);
00088 void init_sim(Devs<X>* model, LpGraph& g);
00089 };
00090
00091 template <class X>
00092 ParSimulator<X>::ParSimulator(Devs<X>* model, MessageManager<X>* msg_manager):
00093 AbstractSimulator<X>(),msg_manager(msg_manager)
00094 {
00095
00096 lp_count = omp_get_max_threads();
00097 LpGraph g;
00098 for (int i = 0; i < lp_count; i++)
00099 {
00100 for (int j = 0; j < lp_count; j++)
00101 {
00102 if (i != j)
00103 {
00104 g.addEdge(i,j);
00105 g.addEdge(j,i);
00106 }
00107 }
00108 }
00109 init_sim(model,g);
00110 }
00111
00112 template <class X>
00113 ParSimulator<X>::ParSimulator(Devs<X>* model, LpGraph& g, MessageManager<X>* msg_manager):
00114 AbstractSimulator<X>(),msg_manager(msg_manager)
00115 {
00116 init_sim(model,g);
00117 }
00118
00119 template <class X>
00120 void ParSimulator<X>::init_sim(Devs<X>* model, LpGraph& g)
00121 {
00122 if (msg_manager == NULL) msg_manager = new NullMessageManager<X>();
00123 lp_count = omp_get_max_threads();
00124 lp = new LogicalProcess<X>*[lp_count];
00125 for (int i = 0; i < lp_count; i++)
00126 {
00127 lp[i] = new LogicalProcess<X>(i,g.getI(i),g.getE(i),lp,this,msg_manager);
00128 }
00129 init(model);
00130 }
00131
00132 template <class X>
00133 double ParSimulator<X>::nextEventTime()
00134 {
00135 Time tN = Time::Inf();
00136 for (int i = 0; i < lp_count; i++)
00137 {
00138 if (lp[i]->getNextEventTime() < tN)
00139 tN = lp[i]->getNextEventTime();
00140 }
00141 return tN.t;
00142 }
00143
00144 template <class X>
00145 ParSimulator<X>::~ParSimulator<X>()
00146 {
00147 for (int i = 0; i < lp_count; i++)
00148 delete lp[i];
00149 delete [] lp;
00150 delete msg_manager;
00151 }
00152
00153 template <class X>
00154 void ParSimulator<X>::execUntil(double tstop)
00155 {
00156 #pragma omp parallel
00157 {
00158 lp[omp_get_thread_num()]->run(tstop);
00159 }
00160 }
00161
00162 template <class X>
00163 void ParSimulator<X>::init(Devs<X>* model)
00164 {
00165 if (model->getProc() >= 0 && model->getProc() < lp_count)
00166 {
00167 lp[model->getProc()]->addModel(model);
00168 return;
00169 }
00170 Atomic<X>* a = model->typeIsAtomic();
00171 if (a != NULL)
00172 {
00173 int lp_assign = a->getProc();
00174 if (lp_assign < 0 || lp_assign >= lp_count)
00175 lp_assign = ((long int)a)%lp_count;
00176 lp[lp_assign]->addModel(a);
00177 }
00178 else
00179 {
00180 Set<Devs<X>*> components;
00181 model->typeIsNetwork()->getComponents(components);
00182 typename Set<Devs<X>*>::iterator iter = components.begin();
00183 for (; iter != components.end(); iter++)
00184 {
00185 init(*iter);
00186 }
00187 }
00188 }
00189
00190 }
00191
00192 #endif