adevs
/home/rotten/adevs-2.6/include/adevs_par_simulator.h
00001 /***************
00002 Copyright (C) 2009 by James Nutaro
00003 
00004 This library is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU Lesser General Public
00006 License as published by the Free Software Foundation; either
00007 version 2 of the License, or (at your option) any later version.
00008 
00009 This library is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 Lesser General Public License for more details.
00013 
00014 You should have received a copy of the GNU Lesser General Public
00015 License along with this library; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 Bugs, comments, and questions can be sent to nutaro@gmail.com
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         // Create an all to all coupling
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 } // end of namespace
00201 
00202 #endif