00001
00031 #ifndef __adevs_par_simulator_h_
00032 #define __adevs_par_simulator_h_
00033 #include "adevs_abstract_simulator.h"
00034 #include "adevs_msg_manager.h"
00035 #include "adevs_lp.h"
00036 #include "adevs_lp_graph.h"
00037 #include <cassert>
00038 #include <cstdlib>
00039 #include <iostream>
00040 #include <vector>
00041 #include <cstdio>
00042
00043 namespace adevs
00044 {
00045
00055 template <class X, class T = double> class ParSimulator:
00056 public AbstractSimulator<X,T>
00057 {
00058 public:
00069 ParSimulator(Devs<X,T>* model, MessageManager<X>* msg_manager = NULL);
00076 ParSimulator(Devs<X,T>* model, LpGraph& g,
00077 MessageManager<X>* msg_manager = NULL);
00079 T nextEventTime();
00085 void execUntil(T stop_time);
00091 ~ParSimulator();
00092 private:
00093 LogicalProcess<X,T>** lp;
00094 int lp_count;
00095 MessageManager<X>* msg_manager;
00096 void init(Devs<X,T>* model);
00097 void init_sim(Devs<X,T>* model, LpGraph& g);
00098 };
00099
00100 template <class X, class T>
00101 ParSimulator<X,T>::ParSimulator(Devs<X,T>* model, MessageManager<X>* msg_manager):
00102 AbstractSimulator<X,T>(),msg_manager(msg_manager)
00103 {
00104
00105 lp_count = omp_get_max_threads();
00106 LpGraph g;
00107 for (int i = 0; i < lp_count; i++)
00108 {
00109 for (int j = 0; j < lp_count; j++)
00110 {
00111 if (i != j)
00112 {
00113 g.addEdge(i,j);
00114 g.addEdge(j,i);
00115 }
00116 }
00117 }
00118 init_sim(model,g);
00119 }
00120
00121 template <class X, class T>
00122 ParSimulator<X,T>::ParSimulator(Devs<X,T>* model, LpGraph& g,
00123 MessageManager<X>* msg_manager):
00124 AbstractSimulator<X,T>(),msg_manager(msg_manager)
00125 {
00126 init_sim(model,g);
00127 }
00128
00129 template <class X, class T>
00130 void ParSimulator<X,T>::init_sim(Devs<X,T>* model, LpGraph& g)
00131 {
00132 if (msg_manager == NULL) msg_manager = new NullMessageManager<X>();
00133 lp_count = g.getLPCount();
00134 if (omp_get_max_threads() < lp_count)
00135 {
00136 char buffer[1000];
00137 sprintf(buffer,"More LPs than threads. Set OMP_NUM_THREADS=%d.",
00138 lp_count);
00139 exception err(buffer);
00140 throw err;
00141 }
00142 omp_set_num_threads(lp_count);
00143 lp = new LogicalProcess<X,T>*[lp_count];
00144 for (int i = 0; i < lp_count; i++)
00145 {
00146 lp[i] = new LogicalProcess<X,T>(i,g.getI(i),g.getE(i),
00147 lp,this,msg_manager);
00148 }
00149 init(model);
00150 }
00151
00152 template <class X, class T>
00153 T ParSimulator<X,T>::nextEventTime()
00154 {
00155 Time<T> tN = Time<T>::Inf();
00156 for (int i = 0; i < lp_count; i++)
00157 {
00158 if (lp[i]->getNextEventTime() < tN)
00159 tN = lp[i]->getNextEventTime();
00160 }
00161 return tN.t;
00162 }
00163
00164 template <class X, class T>
00165 ParSimulator<X,T>::~ParSimulator()
00166 {
00167 for (int i = 0; i < lp_count; i++)
00168 delete lp[i];
00169 delete [] lp;
00170 delete msg_manager;
00171 }
00172
00173 template <class X, class T>
00174 void ParSimulator<X,T>::execUntil(T tstop)
00175 {
00176 #pragma omp parallel
00177 {
00178 lp[omp_get_thread_num()]->run(tstop);
00179 }
00180 }
00181
00182 template <class X, class T>
00183 void ParSimulator<X,T>::init(Devs<X,T>* model)
00184 {
00185 if (model->getProc() >= 0 && model->getProc() < lp_count)
00186 {
00187 lp[model->getProc()]->addModel(model);
00188 return;
00189 }
00190 Atomic<X,T>* a = model->typeIsAtomic();
00191 if (a != NULL)
00192 {
00193 int lp_assign = a->getProc();
00194 if (lp_assign < 0 || lp_assign >= lp_count)
00195 lp_assign =
00196 ((unsigned long int)(a)^(unsigned long int)(this))%lp_count;
00197 lp[lp_assign]->addModel(a);
00198 }
00199 else
00200 {
00201 Set<Devs<X,T>*> components;
00202 model->typeIsNetwork()->getComponents(components);
00203 typename Set<Devs<X,T>*>::iterator iter = components.begin();
00204 for (; iter != components.end(); iter++)
00205 {
00206 init(*iter);
00207 }
00208 }
00209 }
00210
00211 }
00212
00213 #endif