00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef GENERICEVENTHANDLER_HPP_
00031 #define GENERICEVENTHANDLER_HPP_
00032
00033 #include <cassert>
00034 #include <ctime>
00035 #include <iostream>
00036
00037 #include "Exception.hpp"
00038 #include "PetscTools.hpp"
00039
00051 template <unsigned NUM_EVENTS, class CONCRETE>
00052 class GenericEventHandler
00053 {
00054 friend class TestGenericEventHandler;
00055 friend class TestCellBasedEventHandler;
00056 friend class TestHeartEventHandler;
00057
00058 private:
00059 static std::vector<double> mWallTime;
00060 static std::vector<bool> mHasBegun;
00061 static bool mEnabled;
00062 static bool mInitialised;
00063 static bool mInUse;
00072 inline static void MilliSleep(unsigned milliseconds)
00073 {
00074 double start = MPI_Wtime();
00075 double min_Wtime = milliseconds/1000.0 + start;
00076 while (MPI_Wtime() < min_Wtime)
00077 {
00078
00079 }
00080 }
00081
00083 inline static double GetWallTime()
00084 {
00085 return MPI_Wtime();
00086 }
00087
00093 inline static double ConvertWallTimeToMilliseconds(double wallTime)
00094 {
00095 return wallTime*1000.0;
00096 }
00097
00103 inline static double ConvertWallTimeToSeconds(double wallTime)
00104 {
00105 return wallTime;
00106 }
00107
00109 inline static void CheckVectorSizes()
00110 {
00111 if (!mInitialised)
00112 {
00113 mWallTime.resize(NUM_EVENTS, 0.0);
00114 mHasBegun.resize(NUM_EVENTS, false);
00115 mInitialised = true;
00116 }
00117 }
00118
00119 public:
00120
00124 static void Reset()
00125 {
00126 CheckVectorSizes();
00127 for (unsigned event=0; event<NUM_EVENTS; event++)
00128 {
00129 mWallTime[event] = 0.0;
00130 mHasBegun[event] = false;
00131 }
00132 Enable();
00133 mInUse=false;
00134 }
00135
00141 static void BeginEvent(unsigned event) throw (Exception)
00142 {
00143 if (!mEnabled)
00144 {
00145 return;
00146 }
00147 #ifdef CHASTE_EVENT_BARRIERS
00148 PetscTools::Barrier("BeginEvent");
00149 #endif
00150 mInUse = true;
00151 assert(event<NUM_EVENTS);
00152 CheckVectorSizes();
00153
00154 if (event != NUM_EVENTS-1)
00155 {
00156 if (!mHasBegun[NUM_EVENTS-1])
00157 {
00158
00159 BeginEvent(NUM_EVENTS-1);
00160 }
00161 }
00162 if (mHasBegun[event])
00163 {
00164 std::string msg;
00165 msg += "The event associated with the counter for '";
00166 msg += CONCRETE::EventName[event];
00167 msg += "' had already begun when BeginEvent was called.";
00168 std::cerr << msg << std::endl << std::flush;
00169 Disable();
00170 return;
00171 }
00172 mWallTime[event] -= GetWallTime();
00173 mHasBegun[event] = true;
00174
00175 }
00176
00182 static void EndEvent(unsigned event)
00183 {
00184 assert(event<NUM_EVENTS);
00185 if (!mEnabled)
00186 {
00187 return;
00188 }
00189 #ifdef CHASTE_EVENT_BARRIERS
00190 PetscTools::Barrier("EndEvent");
00191 #endif
00192 CheckVectorSizes();
00193 if (!mHasBegun[event])
00194 {
00195 std::string msg;
00196 msg += "Error: The event associated with the counter for '";
00197 msg += CONCRETE::EventName[event];
00198 msg += "' had not begun when EndEvent was called.";
00199 EXCEPTION(msg);
00200 }
00201 mWallTime[event] += GetWallTime();
00202 mHasBegun[event] = false;
00203
00204 }
00205
00213 static double GetElapsedTime(unsigned event)
00214 {
00215 assert(event<NUM_EVENTS);
00216 if (!mEnabled)
00217 {
00218 return 0.0;
00219 }
00220 CheckVectorSizes();
00221 double time;
00222 if (mHasBegun[event])
00223 {
00224 time = mWallTime[event] + GetWallTime();
00225 }
00226 else
00227 {
00228 time = mWallTime[event];
00229 }
00230 return ConvertWallTimeToMilliseconds(time);
00231 }
00232
00241 static void Report()
00242 {
00243 CheckVectorSizes();
00244
00245 if (!mEnabled)
00246 {
00247 EXCEPTION("Asked to report on a disabled event handler. Check for contributory errors above.");
00248 }
00249 if (!mInUse)
00250 {
00251 EXCEPTION("Asked to report on an event handler which is set to zero.");
00252 }
00253
00254 for (unsigned event=0; event<NUM_EVENTS; event++)
00255 {
00256 if (mHasBegun[event])
00257 {
00258
00259 EndEvent(event);
00260 }
00261 }
00262 const unsigned top_event = NUM_EVENTS-1;
00263 double total = ConvertWallTimeToSeconds(mWallTime[top_event]);
00264
00265
00266 const char* format;
00267 if (total > 999999.0)
00268 {
00269 format = "%8.0f ";
00270 }
00271 else if (total > 9999.0)
00272 {
00273 format = "%8.1f ";
00274 }
00275 else
00276 {
00277 format = "%8.3f ";
00278 }
00279
00280 for (unsigned turn=0; turn<PetscTools::GetNumProcs(); turn++)
00281 {
00282 std::cout.flush();
00283 PetscTools::Barrier();
00284 if (turn == PetscTools::GetMyRank())
00285 {
00286 if (PetscTools::IsParallel())
00287 {
00288
00289 printf("%3i: ", turn);
00290 }
00291 for (unsigned event=0; event<NUM_EVENTS; event++)
00292 {
00293 const double secs = ConvertWallTimeToSeconds(mWallTime[event]);
00294 printf(format, secs);
00295 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00296 }
00297 std::cout << "(seconds) \n";
00298 }
00299 }
00300
00301
00302 if (PetscTools::IsParallel())
00303 {
00304 double total_cpu_time[NUM_EVENTS];
00305 MPI_Reduce(&mWallTime[0], total_cpu_time, NUM_EVENTS, MPI_DOUBLE,
00306 MPI_SUM, 0, PETSC_COMM_WORLD);
00307 if (PetscTools::AmMaster())
00308 {
00309 total = ConvertWallTimeToSeconds(total_cpu_time[top_event]);
00310 printf("avg: ");
00311 for (unsigned event=0; event<NUM_EVENTS; event++)
00312 {
00313 const double secs = ConvertWallTimeToSeconds(total_cpu_time[event]);
00314 printf(format, secs/PetscTools::GetNumProcs());
00315 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00316 }
00317 std::cout << "(seconds) \n";
00318 }
00319
00320 double max_cpu_time[NUM_EVENTS];
00321 MPI_Reduce(&mWallTime[0], max_cpu_time, NUM_EVENTS, MPI_DOUBLE,
00322 MPI_MAX, 0, PETSC_COMM_WORLD);
00323 if (PetscTools::AmMaster())
00324 {
00325 total = ConvertWallTimeToSeconds(max_cpu_time[top_event]);
00326 printf("max: ");
00327 for (unsigned event=0; event<NUM_EVENTS; event++)
00328 {
00329 const double secs = ConvertWallTimeToSeconds(max_cpu_time[event]);
00330 printf(format, secs);
00331 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00332 }
00333 std::cout << "(seconds) \n";
00334 }
00335 }
00336 std::cout.flush();
00337 PetscTools::Barrier();
00338 std::cout.flush();
00339
00340 Reset();
00341 }
00342
00346 static void Headings()
00347 {
00348 CheckVectorSizes();
00349
00350 std::cout.flush();
00351 PetscTools::Barrier();
00352 std::cout.flush();
00353 if (PetscTools::AmMaster())
00354 {
00355 if (PetscTools::IsParallel())
00356 {
00357
00358 printf("Proc ");
00359 }
00360 for (unsigned event=0; event<NUM_EVENTS; event++)
00361 {
00362 printf("%15s%2s", CONCRETE::EventName[event], "");
00363 }
00364 std::cout << "\n";
00365 std::cout.flush();
00366 }
00367 }
00368
00372 static void Enable()
00373 {
00374 CheckVectorSizes();
00375 mEnabled = true;
00376 }
00377
00379 static void Disable()
00380 {
00381 CheckVectorSizes();
00382 mEnabled = false;
00383 }
00384
00386 static bool IsEnabled()
00387 {
00388 return mEnabled;
00389 }
00390 };
00391
00392 template<unsigned NUM_EVENTS, class CONCRETE>
00393 std::vector<double> GenericEventHandler<NUM_EVENTS, CONCRETE>::mWallTime;
00394
00395 template<unsigned NUM_EVENTS, class CONCRETE>
00396 std::vector<bool> GenericEventHandler<NUM_EVENTS, CONCRETE>::mHasBegun;
00397
00398 template<unsigned NUM_EVENTS, class CONCRETE>
00399 bool GenericEventHandler<NUM_EVENTS, CONCRETE>::mEnabled = true;
00400
00401 template<unsigned NUM_EVENTS, class CONCRETE>
00402 bool GenericEventHandler<NUM_EVENTS, CONCRETE>::mInitialised = false;
00403
00404 template<unsigned NUM_EVENTS, class CONCRETE>
00405 bool GenericEventHandler<NUM_EVENTS, CONCRETE>::mInUse = false;
00406
00407 #endif