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 <ctime>
00041 #include <iostream>
00042
00043 #include "Exception.hpp"
00044 #include "PetscTools.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 start = MPI_Wtime();
00081 double min_Wtime = milliseconds/1000.0 + start;
00082 while (MPI_Wtime() < min_Wtime)
00083 {
00084
00085 }
00086 }
00087
00089 inline double GetWallTime()
00090 {
00091 return MPI_Wtime();
00092 }
00093
00100 inline double ConvertWallTimeToMilliseconds(double wallTime)
00101 {
00102 return wallTime*1000.0;
00103 }
00104
00111 inline double ConvertWallTimeToSeconds(double wallTime)
00112 {
00113 return wallTime;
00114 }
00115
00116 public:
00117
00121 static GenericEventHandler<NUM_EVENTS, CONCRETE>* Instance()
00122 {
00123 static CONCRETE inst;
00124 return &inst;
00125 }
00126
00130 static void Reset()
00131 {
00132 Instance()->ResetImpl();
00133 }
00134
00140 static void BeginEvent(unsigned event) throw (Exception)
00141 {
00142 Instance()->BeginEventImpl(event);
00143 }
00144
00150 static void EndEvent(unsigned event)
00151 {
00152 Instance()->EndEventImpl(event);
00153 }
00154
00162 static double GetElapsedTime(unsigned event)
00163 {
00164 return Instance()->GetElapsedTimeImpl(event);
00165 }
00166
00175 static void Report()
00176 {
00177 Instance()->ReportImpl();
00178 }
00179
00183 static void Headings()
00184 {
00185 Instance()->HeadingsImpl();
00186 }
00187
00191 static void Enable()
00192 {
00193 Instance()->EnableImpl();
00194 }
00195
00197 static void Disable()
00198 {
00199 Instance()->DisableImpl();
00200 }
00201
00205 static bool IsEnabled()
00206 {
00207 return Instance()->IsEnabledImpl();
00208 }
00209
00210 protected:
00211
00215 GenericEventHandler()
00216 {
00217 mEnabled = true;
00218 mInUse = false;
00219 mWallTime.resize(NUM_EVENTS, 0.0);
00220 mHasBegun.resize(NUM_EVENTS, false);
00221 }
00222
00223 private:
00224
00228 void ResetImpl()
00229 {
00230 for (unsigned event=0; event<NUM_EVENTS; event++)
00231 {
00232 mWallTime[event] = 0.0;
00233 mHasBegun[event] = false;
00234 }
00235 Enable();
00236 mInUse = false;
00237 }
00238
00244 void BeginEventImpl(unsigned event) throw (Exception)
00245 {
00246 if (!mEnabled)
00247 {
00248 return;
00249 }
00250 #ifdef CHASTE_EVENT_BARRIERS
00251 PetscTools::Barrier("BeginEvent");
00252 #endif
00253 mInUse = true;
00254 assert(event<NUM_EVENTS);
00255
00256 if (event != NUM_EVENTS-1)
00257 {
00258 if (!mHasBegun[NUM_EVENTS-1])
00259 {
00260
00261 BeginEvent(NUM_EVENTS-1);
00262 }
00263 }
00264 if (mHasBegun[event])
00265 {
00266 std::string msg;
00267 msg += "The event associated with the counter for '";
00268 msg += CONCRETE::EventName[event];
00269 msg += "' had already begun when BeginEvent was called.";
00270 std::cerr << msg << std::endl << std::flush;
00271 Disable();
00272 return;
00273 }
00274 mWallTime[event] -= GetWallTime();
00275 mHasBegun[event] = true;
00276
00277 }
00278
00284 void EndEventImpl(unsigned event)
00285 {
00286 assert(event<NUM_EVENTS);
00287 if (!mEnabled)
00288 {
00289 return;
00290 }
00291 #ifdef CHASTE_EVENT_BARRIERS
00292 PetscTools::Barrier("EndEvent");
00293 #endif
00294 if (!mHasBegun[event])
00295 {
00296 std::string msg;
00297 msg += "Error: The event associated with the counter for '";
00298 msg += CONCRETE::EventName[event];
00299 msg += "' had not begun when EndEvent was called.";
00300 EXCEPTION(msg);
00301 }
00302 mWallTime[event] += GetWallTime();
00303 mHasBegun[event] = false;
00304
00305 }
00306
00314 double GetElapsedTimeImpl(unsigned event)
00315 {
00316 assert(event<NUM_EVENTS);
00317 if (!mEnabled)
00318 {
00319 return 0.0;
00320 }
00321 double time;
00322 if (mHasBegun[event])
00323 {
00324 time = mWallTime[event] + GetWallTime();
00325 }
00326 else
00327 {
00328 time = mWallTime[event];
00329 }
00330 return ConvertWallTimeToMilliseconds(time);
00331 }
00332
00341 void ReportImpl()
00342 {
00343 if (!mEnabled)
00344 {
00345 EXCEPTION("Asked to report on a disabled event handler. Check for contributory errors above.");
00346 }
00347 if (!mInUse)
00348 {
00349 EXCEPTION("Asked to report on an event handler which is set to zero.");
00350 }
00351
00352 for (unsigned event=0; event<NUM_EVENTS; event++)
00353 {
00354 if (mHasBegun[event])
00355 {
00356
00357 EndEvent(event);
00358 }
00359 }
00360 const unsigned top_event = NUM_EVENTS-1;
00361 double total = ConvertWallTimeToSeconds(mWallTime[top_event]);
00362
00363
00364 const char* format;
00365 if (total > 999999.0)
00366 {
00367 format = "%8.0f ";
00368 }
00369 else if (total > 9999.0)
00370 {
00371 format = "%8.1f ";
00372 }
00373 else
00374 {
00375 format = "%8.3f ";
00376 }
00377
00378 PetscTools::BeginRoundRobin();
00379 {
00380 std::cout.flush();
00381 if (PetscTools::IsParallel())
00382 {
00383
00384 printf("%3u: ", PetscTools::GetMyRank());
00385 }
00386 for (unsigned event=0; event<NUM_EVENTS; event++)
00387 {
00388 const double secs = ConvertWallTimeToSeconds(mWallTime[event]);
00389 printf(format, secs);
00390 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00391 }
00392 std::cout << "(seconds) \n";
00393 }
00394 PetscTools::EndRoundRobin();
00395
00396
00397 if (PetscTools::IsParallel() && !PetscTools::IsIsolated())
00398 {
00399 double total_cpu_time[NUM_EVENTS];
00400 MPI_Reduce(&mWallTime[0], total_cpu_time, NUM_EVENTS, MPI_DOUBLE, MPI_SUM, 0, PetscTools::GetWorld());
00401 if (PetscTools::AmMaster())
00402 {
00403 total = ConvertWallTimeToSeconds(total_cpu_time[top_event]);
00404 printf("avg: ");
00405 for (unsigned event=0; event<NUM_EVENTS; event++)
00406 {
00407 const double secs = ConvertWallTimeToSeconds(total_cpu_time[event]);
00408 printf(format, secs/PetscTools::GetNumProcs());
00409 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00410 }
00411 std::cout << "(seconds) \n";
00412 }
00413
00414 double max_cpu_time[NUM_EVENTS];
00415 MPI_Reduce(&mWallTime[0], max_cpu_time, NUM_EVENTS, MPI_DOUBLE, MPI_MAX, 0, PetscTools::GetWorld());
00416 if (PetscTools::AmMaster())
00417 {
00418 total = ConvertWallTimeToSeconds(max_cpu_time[top_event]);
00419 printf("max: ");
00420 for (unsigned event=0; event<NUM_EVENTS; event++)
00421 {
00422 const double secs = ConvertWallTimeToSeconds(max_cpu_time[event]);
00423 printf(format, secs);
00424 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00425 }
00426 std::cout << "(seconds) \n";
00427 }
00428 }
00429 std::cout.flush();
00430 PetscTools::Barrier();
00431 std::cout.flush();
00432
00433 Reset();
00434 }
00435
00439 void HeadingsImpl()
00440 {
00441
00442 std::cout.flush();
00443 PetscTools::Barrier();
00444 std::cout.flush();
00445 if (PetscTools::AmMaster())
00446 {
00447 if (PetscTools::IsParallel())
00448 {
00449
00450 printf("Proc ");
00451 }
00452 for (unsigned event=0; event<NUM_EVENTS; event++)
00453 {
00454 printf("%15s%2s", CONCRETE::EventName[event], "");
00455 }
00456 std::cout << "\n";
00457 std::cout.flush();
00458 }
00459 }
00460
00462 void EnableImpl()
00463 {
00464 mEnabled = true;
00465 }
00466
00468 void DisableImpl()
00469 {
00470 mEnabled = false;
00471 }
00472
00476 bool IsEnabledImpl()
00477 {
00478 return mEnabled;
00479 }
00480 };
00481
00482 #endif