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
00030
00031
00032
00033
00034
00035
00036 #ifndef GENERICEVENTHANDLER_HPP_
00037 #define GENERICEVENTHANDLER_HPP_
00038
00039 #include <cassert>
00040 #include <iostream>
00041
00042 #include "Exception.hpp"
00043 #include "PetscTools.hpp"
00044 #include "Timer.hpp"
00045
00057 template <unsigned NUM_EVENTS, class CONCRETE>
00058 class GenericEventHandler
00059 {
00060 friend class TestGenericEventHandler;
00061 friend class TestCellBasedEventHandler;
00062 friend class TestHeartEventHandler;
00063
00064 private:
00065
00066 std::vector<double> mWallTime;
00067 std::vector<bool> mHasBegun;
00068 bool mEnabled;
00069 bool mInUse;
00078 static inline void MilliSleep(unsigned milliseconds)
00079 {
00080 double min_Wtime = milliseconds/1000.0 + Timer::GetElapsedTime();
00081 while (Timer::GetElapsedTime() < min_Wtime)
00082 {
00083
00084 }
00085 }
00086
00093 inline double ConvertWallTimeToMilliseconds(double wallTime)
00094 {
00095 return wallTime*1000.0;
00096 }
00097
00104 inline double ConvertWallTimeToSeconds(double wallTime)
00105 {
00106 return wallTime;
00107 }
00108
00109 public:
00110
00114 static GenericEventHandler<NUM_EVENTS, CONCRETE>* Instance()
00115 {
00116 static CONCRETE inst;
00117 return &inst;
00118 }
00119
00123 static void Reset()
00124 {
00125 Instance()->ResetImpl();
00126 }
00127
00133 static void BeginEvent(unsigned event) throw (Exception)
00134 {
00135 Instance()->BeginEventImpl(event);
00136 }
00137
00143 static void EndEvent(unsigned event)
00144 {
00145 Instance()->EndEventImpl(event);
00146 }
00147
00155 static double GetElapsedTime(unsigned event)
00156 {
00157 return Instance()->GetElapsedTimeImpl(event);
00158 }
00159
00168 static void Report()
00169 {
00170 Instance()->ReportImpl();
00171 }
00172
00176 static void Headings()
00177 {
00178 Instance()->HeadingsImpl();
00179 }
00180
00184 static void Enable()
00185 {
00186 Instance()->EnableImpl();
00187 }
00188
00190 static void Disable()
00191 {
00192 Instance()->DisableImpl();
00193 }
00194
00198 static bool IsEnabled()
00199 {
00200 return Instance()->IsEnabledImpl();
00201 }
00202
00203 protected:
00204
00208 GenericEventHandler()
00209 {
00210 mEnabled = true;
00211 mInUse = false;
00212 mWallTime.resize(NUM_EVENTS, 0.0);
00213 mHasBegun.resize(NUM_EVENTS, false);
00214 }
00215
00216 private:
00217
00221 void ResetImpl()
00222 {
00223 for (unsigned event=0; event<NUM_EVENTS; event++)
00224 {
00225 mWallTime[event] = 0.0;
00226 mHasBegun[event] = false;
00227 }
00228 Enable();
00229 mInUse = false;
00230 }
00231
00237 void BeginEventImpl(unsigned event) throw (Exception)
00238 {
00239 if (!mEnabled)
00240 {
00241 return;
00242 }
00243 #ifdef CHASTE_EVENT_BARRIERS
00244 PetscTools::Barrier("BeginEvent");
00245 #endif
00246 mInUse = true;
00247 assert(event<NUM_EVENTS);
00248
00249 if (event != NUM_EVENTS-1)
00250 {
00251 if (!mHasBegun[NUM_EVENTS-1])
00252 {
00253
00254 BeginEvent(NUM_EVENTS-1);
00255 }
00256 }
00257 if (mHasBegun[event])
00258 {
00259 std::string msg;
00260 msg += "The event associated with the counter for '";
00261 msg += CONCRETE::EventName[event];
00262 msg += "' had already begun when BeginEvent was called.";
00263 std::cerr << msg << std::endl << std::flush;
00264 Disable();
00265 return;
00266 }
00267 mWallTime[event] -= Timer::GetWallTime();
00268 mHasBegun[event] = true;
00269
00270 }
00271
00277 void EndEventImpl(unsigned event)
00278 {
00279 assert(event<NUM_EVENTS);
00280 if (!mEnabled)
00281 {
00282 return;
00283 }
00284 #ifdef CHASTE_EVENT_BARRIERS
00285 PetscTools::Barrier("EndEvent");
00286 #endif
00287 if (!mHasBegun[event])
00288 {
00289 std::string msg;
00290 msg += "Error: The event associated with the counter for '";
00291 msg += CONCRETE::EventName[event];
00292 msg += "' had not begun when EndEvent was called.";
00293 EXCEPTION(msg);
00294 }
00295 mWallTime[event] += Timer::GetWallTime();
00296 mHasBegun[event] = false;
00297
00298 }
00299
00307 double GetElapsedTimeImpl(unsigned event)
00308 {
00309 assert(event<NUM_EVENTS);
00310 if (!mEnabled)
00311 {
00312 return 0.0;
00313 }
00314 double time;
00315 if (mHasBegun[event])
00316 {
00317 time = mWallTime[event] + Timer::GetWallTime();
00318 }
00319 else
00320 {
00321 time = mWallTime[event];
00322 }
00323 return ConvertWallTimeToMilliseconds(time);
00324 }
00325
00334 void ReportImpl()
00335 {
00336 if (!mEnabled)
00337 {
00338 EXCEPTION("Asked to report on a disabled event handler. Check for contributory errors above.");
00339 }
00340 if (!mInUse)
00341 {
00342 EXCEPTION("Asked to report on an event handler which is set to zero.");
00343 }
00344
00345 for (unsigned event=0; event<NUM_EVENTS; event++)
00346 {
00347 if (mHasBegun[event])
00348 {
00349
00350 EndEvent(event);
00351 }
00352 }
00353 const unsigned top_event = NUM_EVENTS-1;
00354 double total = ConvertWallTimeToSeconds(mWallTime[top_event]);
00355
00356
00357 const char* format;
00358 if (total > 999999.0)
00359 {
00360 format = "%8.0f ";
00361 }
00362 else if (total > 9999.0)
00363 {
00364 format = "%8.1f ";
00365 }
00366 else
00367 {
00368 format = "%8.3f ";
00369 }
00370
00371 PetscTools::BeginRoundRobin();
00372 {
00373 std::cout.flush();
00374 if (PetscTools::IsParallel())
00375 {
00376
00377 printf("%3u: ", PetscTools::GetMyRank());
00378 }
00379 for (unsigned event=0; event<NUM_EVENTS; event++)
00380 {
00381 const double secs = ConvertWallTimeToSeconds(mWallTime[event]);
00382 printf(format, secs);
00383 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00384 }
00385 std::cout << "(seconds) \n";
00386 }
00387 PetscTools::EndRoundRobin();
00388
00389
00390 if (PetscTools::IsParallel() && !PetscTools::IsIsolated())
00391 {
00392 double total_cpu_time[NUM_EVENTS];
00393 MPI_Reduce(&mWallTime[0], total_cpu_time, NUM_EVENTS, MPI_DOUBLE, MPI_SUM, 0, PetscTools::GetWorld());
00394 if (PetscTools::AmMaster())
00395 {
00396 total = ConvertWallTimeToSeconds(total_cpu_time[top_event]);
00397 printf("avg: ");
00398 for (unsigned event=0; event<NUM_EVENTS; event++)
00399 {
00400 const double secs = ConvertWallTimeToSeconds(total_cpu_time[event]);
00401 printf(format, secs/PetscTools::GetNumProcs());
00402 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00403 }
00404 std::cout << "(seconds) \n";
00405 }
00406
00407 double max_cpu_time[NUM_EVENTS];
00408 MPI_Reduce(&mWallTime[0], max_cpu_time, NUM_EVENTS, MPI_DOUBLE, MPI_MAX, 0, PetscTools::GetWorld());
00409 if (PetscTools::AmMaster())
00410 {
00411 total = ConvertWallTimeToSeconds(max_cpu_time[top_event]);
00412 printf("max: ");
00413 for (unsigned event=0; event<NUM_EVENTS; event++)
00414 {
00415 const double secs = ConvertWallTimeToSeconds(max_cpu_time[event]);
00416 printf(format, secs);
00417 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00418 }
00419 std::cout << "(seconds) \n";
00420 }
00421 }
00422 std::cout.flush();
00423 PetscTools::Barrier();
00424 std::cout.flush();
00425
00426 Reset();
00427 }
00428
00432 void HeadingsImpl()
00433 {
00434
00435 std::cout.flush();
00436 PetscTools::Barrier();
00437 std::cout.flush();
00438 if (PetscTools::AmMaster())
00439 {
00440 if (PetscTools::IsParallel())
00441 {
00442
00443 printf("Proc ");
00444 }
00445 for (unsigned event=0; event<NUM_EVENTS; event++)
00446 {
00447 printf("%15s%2s", CONCRETE::EventName[event], "");
00448 }
00449 std::cout << "\n";
00450 std::cout.flush();
00451 }
00452 }
00453
00455 void EnableImpl()
00456 {
00457 mEnabled = true;
00458 }
00459
00461 void DisableImpl()
00462 {
00463 mEnabled = false;
00464 }
00465
00469 bool IsEnabledImpl()
00470 {
00471 return mEnabled;
00472 }
00473 };
00474
00475 #endif