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 #include <cstdio>
00031
00032 namespace adevs
00033 {
00034
00044 template <class X, class T = double> class ParSimulator:
00045 public AbstractSimulator<X,T>
00046 {
00047 public:
00058 ParSimulator(Devs<X,T>* model, MessageManager<X>* msg_manager = NULL);
00065 ParSimulator(Devs<X,T>* model, LpGraph& g,
00066 MessageManager<X>* msg_manager = NULL);
00068 T nextEventTime();
00074 void execUntil(T stop_time);
00080 ~ParSimulator();
00081 private:
00082 LogicalProcess<X,T>** lp;
00083 int lp_count;
00084 MessageManager<X>* msg_manager;
00085 void init(Devs<X,T>* model);
00086 void init_sim(Devs<X,T>* model, LpGraph& g);
00087 };
00088
00089 template <class X, class T>
00090 ParSimulator<X,T>::ParSimulator(Devs<X,T>* model, MessageManager<X>* msg_manager):
00091 AbstractSimulator<X,T>(),msg_manager(msg_manager)
00092 {
00093
00094 lp_count = omp_get_max_threads();
00095 LpGraph g;
00096 for (int i = 0; i < lp_count; i++)
00097 {
00098 for (int j = 0; j < lp_count; j++)
00099 {
00100 if (i != j)
00101 {
00102 g.addEdge(i,j);
00103 g.addEdge(j,i);
00104 }
00105 }
00106 }
00107 init_sim(model,g);
00108 }
00109
00110 template <class X, class T>
00111 ParSimulator<X,T>::ParSimulator(Devs<X,T>* model, LpGraph& g,
00112 MessageManager<X>* msg_manager):
00113 AbstractSimulator<X,T>(),msg_manager(msg_manager)
00114 {
00115 init_sim(model,g);
00116 }
00117
00118 template <class X, class T>
00119 void ParSimulator<X,T>::init_sim(Devs<X,T>* model, LpGraph& g)
00120 {
00121 if (msg_manager == NULL) msg_manager = new NullMessageManager<X>();
00122 lp_count = g.getLPCount();
00123 if (omp_get_max_threads() < lp_count)
00124 {
00125 char buffer[1000];
00126 sprintf(buffer,"More LPs than threads. Set OMP_NUM_THREADS=%d.",
00127 lp_count);
00128 exception err(buffer);
00129 throw err;
00130 }
00131 omp_set_num_threads(lp_count);
00132 lp = new LogicalProcess<X,T>*[lp_count];
00133 for (int i = 0; i < lp_count; i++)
00134 {
00135 lp[i] = new LogicalProcess<X,T>(i,g.getI(i),g.getE(i),
00136 lp,this,msg_manager);
00137 }
00138 init(model);
00139 }
00140
00141 template <class X, class T>
00142 T ParSimulator<X,T>::nextEventTime()
00143 {
00144 Time<T> tN = Time<T>::Inf();
00145 for (int i = 0; i < lp_count; i++)
00146 {
00147 if (lp[i]->getNextEventTime() < tN)
00148 tN = lp[i]->getNextEventTime();
00149 }
00150 return tN.t;
00151 }
00152
00153 template <class X, class T>
00154 ParSimulator<X,T>::~ParSimulator()
00155 {
00156 for (int i = 0; i < lp_count; i++)
00157 delete lp[i];
00158 delete [] lp;
00159 delete msg_manager;
00160 }
00161
00162 template <class X, class T>
00163 void ParSimulator<X,T>::execUntil(T tstop)
00164 {
00165 #pragma omp parallel
00166 {
00167 lp[omp_get_thread_num()]->run(tstop);
00168 }
00169 }
00170
00171 template <class X, class T>
00172 void ParSimulator<X,T>::init(Devs<X,T>* model)
00173 {
00174 if (model->getProc() >= 0 && model->getProc() < lp_count)
00175 {
00176 lp[model->getProc()]->addModel(model);
00177 return;
00178 }
00179 Atomic<X,T>* a = model->typeIsAtomic();
00180 if (a != NULL)
00181 {
00182 int lp_assign = a->getProc();
00183 if (lp_assign < 0 || lp_assign >= lp_count)
00184 lp_assign =
00185 ((unsigned long int)(a)^(unsigned long int)(this))%lp_count;
00186 lp[lp_assign]->addModel(a);
00187 }
00188 else
00189 {
00190 Set<Devs<X,T>*> components;
00191 model->typeIsNetwork()->getComponents(components);
00192 typename Set<Devs<X,T>*>::iterator iter = components.begin();
00193 for (; iter != components.end(); iter++)
00194 {
00195 init(*iter);
00196 }
00197 }
00198 }
00199
00200 }
00201
00202 #endif