GenericEventHandler.hpp
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 #ifndef GENERICEVENTHANDLER_HPP_
00030 #define GENERICEVENTHANDLER_HPP_
00031
00032 #include <cassert>
00033 #include <ctime>
00034 #include <iostream>
00035
00036 #include "Exception.hpp"
00037 #include "PetscTools.hpp"
00038
00050 template <unsigned NUM_EVENTS, class CONCRETE>
00051 class GenericEventHandler
00052 {
00053 friend class TestGenericEventHandler;
00054 friend class TestCellBasedEventHandler;
00055 friend class TestHeartEventHandler;
00056
00057 private:
00058
00059 std::vector<double> mWallTime;
00060 std::vector<bool> mHasBegun;
00061 bool mEnabled;
00062 bool mInUse;
00071 static inline void MilliSleep(unsigned milliseconds)
00072 {
00073 double start = MPI_Wtime();
00074 double min_Wtime = milliseconds/1000.0 + start;
00075 while (MPI_Wtime() < min_Wtime)
00076 {
00077
00078 }
00079 }
00080
00082 inline double GetWallTime()
00083 {
00084 return MPI_Wtime();
00085 }
00086
00092 inline double ConvertWallTimeToMilliseconds(double wallTime)
00093 {
00094 return wallTime*1000.0;
00095 }
00096
00102 inline double ConvertWallTimeToSeconds(double wallTime)
00103 {
00104 return wallTime;
00105 }
00106
00107 public:
00108
00112 static GenericEventHandler<NUM_EVENTS, CONCRETE>* Instance()
00113 {
00114 static CONCRETE inst;
00115 return &inst;
00116 }
00117
00121 static void Reset()
00122 {
00123 Instance()->ResetImpl();
00124 }
00125
00131 static void BeginEvent(unsigned event) throw (Exception)
00132 {
00133 Instance()->BeginEventImpl(event);
00134 }
00135
00141 static void EndEvent(unsigned event)
00142 {
00143 Instance()->EndEventImpl(event);
00144 }
00145
00153 static double GetElapsedTime(unsigned event)
00154 {
00155 return Instance()->GetElapsedTimeImpl(event);
00156 }
00157
00166 static void Report()
00167 {
00168 Instance()->ReportImpl();
00169 }
00170
00174 static void Headings()
00175 {
00176 Instance()->HeadingsImpl();
00177 }
00178
00182 static void Enable()
00183 {
00184 Instance()->EnableImpl();
00185 }
00186
00188 static void Disable()
00189 {
00190 Instance()->DisableImpl();
00191 }
00192
00194 static bool IsEnabled()
00195 {
00196 return Instance()->IsEnabledImpl();
00197 }
00198
00199 protected:
00200
00204 GenericEventHandler()
00205 {
00206 mEnabled = true;
00207 mInUse = false;
00208 mWallTime.resize(NUM_EVENTS, 0.0);
00209 mHasBegun.resize(NUM_EVENTS, false);
00210 }
00211
00212 private:
00213
00217 void ResetImpl()
00218 {
00219 for (unsigned event=0; event<NUM_EVENTS; event++)
00220 {
00221 mWallTime[event] = 0.0;
00222 mHasBegun[event] = false;
00223 }
00224 Enable();
00225 mInUse = false;
00226 }
00227
00233 void BeginEventImpl(unsigned event) throw (Exception)
00234 {
00235 if (!mEnabled)
00236 {
00237 return;
00238 }
00239 #ifdef CHASTE_EVENT_BARRIERS
00240 PetscTools::Barrier("BeginEvent");
00241 #endif
00242 mInUse = true;
00243 assert(event<NUM_EVENTS);
00244
00245 if (event != NUM_EVENTS-1)
00246 {
00247 if (!mHasBegun[NUM_EVENTS-1])
00248 {
00249
00250 BeginEvent(NUM_EVENTS-1);
00251 }
00252 }
00253 if (mHasBegun[event])
00254 {
00255 std::string msg;
00256 msg += "The event associated with the counter for '";
00257 msg += CONCRETE::EventName[event];
00258 msg += "' had already begun when BeginEvent was called.";
00259 std::cerr << msg << std::endl << std::flush;
00260 Disable();
00261 return;
00262 }
00263 mWallTime[event] -= GetWallTime();
00264 mHasBegun[event] = true;
00265
00266 }
00267
00273 void EndEventImpl(unsigned event)
00274 {
00275 assert(event<NUM_EVENTS);
00276 if (!mEnabled)
00277 {
00278 return;
00279 }
00280 #ifdef CHASTE_EVENT_BARRIERS
00281 PetscTools::Barrier("EndEvent");
00282 #endif
00283 if (!mHasBegun[event])
00284 {
00285 std::string msg;
00286 msg += "Error: The event associated with the counter for '";
00287 msg += CONCRETE::EventName[event];
00288 msg += "' had not begun when EndEvent was called.";
00289 EXCEPTION(msg);
00290 }
00291 mWallTime[event] += GetWallTime();
00292 mHasBegun[event] = false;
00293
00294 }
00295
00303 double GetElapsedTimeImpl(unsigned event)
00304 {
00305 assert(event<NUM_EVENTS);
00306 if (!mEnabled)
00307 {
00308 return 0.0;
00309 }
00310 double time;
00311 if (mHasBegun[event])
00312 {
00313 time = mWallTime[event] + GetWallTime();
00314 }
00315 else
00316 {
00317 time = mWallTime[event];
00318 }
00319 return ConvertWallTimeToMilliseconds(time);
00320 }
00321
00330 void ReportImpl()
00331 {
00332 if (!mEnabled)
00333 {
00334 EXCEPTION("Asked to report on a disabled event handler. Check for contributory errors above.");
00335 }
00336 if (!mInUse)
00337 {
00338 EXCEPTION("Asked to report on an event handler which is set to zero.");
00339 }
00340
00341 for (unsigned event=0; event<NUM_EVENTS; event++)
00342 {
00343 if (mHasBegun[event])
00344 {
00345
00346 EndEvent(event);
00347 }
00348 }
00349 const unsigned top_event = NUM_EVENTS-1;
00350 double total = ConvertWallTimeToSeconds(mWallTime[top_event]);
00351
00352
00353 const char* format;
00354 if (total > 999999.0)
00355 {
00356 format = "%8.0f ";
00357 }
00358 else if (total > 9999.0)
00359 {
00360 format = "%8.1f ";
00361 }
00362 else
00363 {
00364 format = "%8.3f ";
00365 }
00366
00367 PetscTools::BeginRoundRobin();
00368 {
00369 std::cout.flush();
00370 if (PetscTools::IsParallel())
00371 {
00372
00373 printf("%3i: ", PetscTools::GetMyRank());
00374 }
00375 for (unsigned event=0; event<NUM_EVENTS; event++)
00376 {
00377 const double secs = ConvertWallTimeToSeconds(mWallTime[event]);
00378 printf(format, secs);
00379 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00380 }
00381 std::cout << "(seconds) \n";
00382 }
00383 PetscTools::EndRoundRobin();
00384
00385
00386 if (PetscTools::IsParallel())
00387 {
00388 double total_cpu_time[NUM_EVENTS];
00389 MPI_Reduce(&mWallTime[0], total_cpu_time, NUM_EVENTS, MPI_DOUBLE, MPI_SUM, 0, PETSC_COMM_WORLD);
00390 if (PetscTools::AmMaster())
00391 {
00392 total = ConvertWallTimeToSeconds(total_cpu_time[top_event]);
00393 printf("avg: ");
00394 for (unsigned event=0; event<NUM_EVENTS; event++)
00395 {
00396 const double secs = ConvertWallTimeToSeconds(total_cpu_time[event]);
00397 printf(format, secs/PetscTools::GetNumProcs());
00398 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00399 }
00400 std::cout << "(seconds) \n";
00401 }
00402
00403 double max_cpu_time[NUM_EVENTS];
00404 MPI_Reduce(&mWallTime[0], max_cpu_time, NUM_EVENTS, MPI_DOUBLE, MPI_MAX, 0, PETSC_COMM_WORLD);
00405 if (PetscTools::AmMaster())
00406 {
00407 total = ConvertWallTimeToSeconds(max_cpu_time[top_event]);
00408 printf("max: ");
00409 for (unsigned event=0; event<NUM_EVENTS; event++)
00410 {
00411 const double secs = ConvertWallTimeToSeconds(max_cpu_time[event]);
00412 printf(format, secs);
00413 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00414 }
00415 std::cout << "(seconds) \n";
00416 }
00417 }
00418 std::cout.flush();
00419 PetscTools::Barrier();
00420 std::cout.flush();
00421
00422 Reset();
00423 }
00424
00428 void HeadingsImpl()
00429 {
00430
00431 std::cout.flush();
00432 PetscTools::Barrier();
00433 std::cout.flush();
00434 if (PetscTools::AmMaster())
00435 {
00436 if (PetscTools::IsParallel())
00437 {
00438
00439 printf("Proc ");
00440 }
00441 for (unsigned event=0; event<NUM_EVENTS; event++)
00442 {
00443 printf("%15s%2s", CONCRETE::EventName[event], "");
00444 }
00445 std::cout << "\n";
00446 std::cout.flush();
00447 }
00448 }
00449
00451 void EnableImpl()
00452 {
00453 mEnabled = true;
00454 }
00455
00457 void DisableImpl()
00458 {
00459 mEnabled = false;
00460 }
00461
00463 bool IsEnabledImpl()
00464 {
00465 return mEnabled;
00466 }
00467 };
00468
00469 #endif