adevs
|
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