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
00042 template <class X> class ParSimulator:
00043 public AbstractSimulator<X>
00044 {
00045 public:
00056 ParSimulator(Devs<X>* model, MessageManager<X>* msg_manager = NULL);
00063 ParSimulator(Devs<X>* model, LpGraph& g, MessageManager<X>* msg_manager = NULL);
00065 double nextEventTime();
00071 void execUntil(double stop_time);
00077 ~ParSimulator();
00078 private:
00079 LogicalProcess<X>** lp;
00080 int lp_count;
00081 MessageManager<X>* msg_manager;
00082 void init(Devs<X>* model);
00083 void init_sim(Devs<X>* model, LpGraph& g);
00084 };
00085
00086 template <class X>
00087 ParSimulator<X>::ParSimulator(Devs<X>* model, MessageManager<X>* msg_manager):
00088 AbstractSimulator<X>(),msg_manager(msg_manager)
00089 {
00090
00091 lp_count = omp_get_max_threads();
00092 LpGraph g;
00093 for (int i = 0; i < lp_count; i++)
00094 {
00095 for (int j = 0; j < lp_count; j++)
00096 {
00097 if (i != j)
00098 {
00099 g.addEdge(i,j);
00100 g.addEdge(j,i);
00101 }
00102 }
00103 }
00104 init_sim(model,g);
00105 }
00106
00107 template <class X>
00108 ParSimulator<X>::ParSimulator(Devs<X>* model, LpGraph& g, MessageManager<X>* msg_manager):
00109 AbstractSimulator<X>(),msg_manager(msg_manager)
00110 {
00111 init_sim(model,g);
00112 }
00113
00114 template <class X>
00115 void ParSimulator<X>::init_sim(Devs<X>* model, LpGraph& g)
00116 {
00117 if (msg_manager == NULL) msg_manager = new NullMessageManager<X>();
00118 lp_count = omp_get_max_threads();
00119 lp = new LogicalProcess<X>*[lp_count];
00120 for (int i = 0; i < lp_count; i++)
00121 {
00122 lp[i] = new LogicalProcess<X>(i,g.getI(i),g.getE(i),lp,this,msg_manager);
00123 }
00124 init(model);
00125 }
00126
00127 template <class X>
00128 double ParSimulator<X>::nextEventTime()
00129 {
00130 Time tN = Time::Inf();
00131 for (int i = 0; i < lp_count; i++)
00132 {
00133 if (lp[i]->getNextEventTime() < tN)
00134 tN = lp[i]->getNextEventTime();
00135 }
00136 return tN.t;
00137 }
00138
00139 template <class X>
00140 ParSimulator<X>::~ParSimulator<X>()
00141 {
00142 for (int i = 0; i < lp_count; i++)
00143 delete lp[i];
00144 delete [] lp;
00145 delete msg_manager;
00146 }
00147
00148 template <class X>
00149 void ParSimulator<X>::execUntil(double tstop)
00150 {
00151 #pragma omp parallel
00152 {
00153 lp[omp_get_thread_num()]->run(tstop);
00154 }
00155 }
00156
00157 template <class X>
00158 void ParSimulator<X>::init(Devs<X>* model)
00159 {
00160 if (model->getProc() >= 0 && model->getProc() < lp_count)
00161 {
00162 lp[model->getProc()]->addModel(model);
00163 return;
00164 }
00165 Atomic<X>* a = model->typeIsAtomic();
00166 if (a != NULL)
00167 {
00168 int lp_assign = a->getProc();
00169 if (lp_assign < 0 || lp_assign >= lp_count)
00170 lp_assign = ((long int)a)%lp_count;
00171 lp[lp_assign]->addModel(a);
00172 }
00173 else
00174 {
00175 Set<Devs<X>*> components;
00176 model->typeIsNetwork()->getComponents(components);
00177 typename Set<Devs<X>*>::iterator iter = components.begin();
00178 for (; iter != components.end(); iter++)
00179 {
00180 init(*iter);
00181 }
00182 }
00183 }
00184
00185 }
00186
00187 #endif