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 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:
00111 static GenericEventHandler<NUM_EVENTS, CONCRETE>* Instance()
00112 {
00113 static CONCRETE inst;
00114 return &inst;
00115 }
00116
00120 static void Reset()
00121 {
00122 Instance()->ResetImpl();
00123 }
00124
00130 static void BeginEvent(unsigned event) throw (Exception)
00131 {
00132 Instance()->BeginEventImpl(event);
00133 }
00134
00140 static void EndEvent(unsigned event)
00141 {
00142 Instance()->EndEventImpl(event);
00143 }
00144
00152 static double GetElapsedTime(unsigned event)
00153 {
00154 return Instance()->GetElapsedTimeImpl(event);
00155 }
00156
00165 static void Report()
00166 {
00167 Instance()->ReportImpl();
00168 }
00169
00173 static void Headings()
00174 {
00175 Instance()->HeadingsImpl();
00176 }
00177
00181 static void Enable()
00182 {
00183 Instance()->EnableImpl();
00184 }
00185
00187 static void Disable()
00188 {
00189 Instance()->DisableImpl();
00190 }
00191
00193 static bool IsEnabled()
00194 {
00195 return Instance()->IsEnabledImpl();
00196 }
00197
00198 protected:
00202 GenericEventHandler()
00203 {
00204 mEnabled = true;
00205 mInUse = false;
00206 mWallTime.resize(NUM_EVENTS, 0.0);
00207 mHasBegun.resize(NUM_EVENTS, false);
00208 }
00209
00210 private:
00214 void ResetImpl()
00215 {
00216 for (unsigned event=0; event<NUM_EVENTS; event++)
00217 {
00218 mWallTime[event] = 0.0;
00219 mHasBegun[event] = false;
00220 }
00221 Enable();
00222 mInUse=false;
00223 }
00224
00230 void BeginEventImpl(unsigned event) throw (Exception)
00231 {
00232 if (!mEnabled)
00233 {
00234 return;
00235 }
00236 #ifdef CHASTE_EVENT_BARRIERS
00237 PetscTools::Barrier("BeginEvent");
00238 #endif
00239 mInUse = true;
00240 assert(event<NUM_EVENTS);
00241
00242 if (event != NUM_EVENTS-1)
00243 {
00244 if (!mHasBegun[NUM_EVENTS-1])
00245 {
00246
00247 BeginEvent(NUM_EVENTS-1);
00248 }
00249 }
00250 if (mHasBegun[event])
00251 {
00252 std::string msg;
00253 msg += "The event associated with the counter for '";
00254 msg += CONCRETE::EventName[event];
00255 msg += "' had already begun when BeginEvent was called.";
00256 std::cerr << msg << std::endl << std::flush;
00257 Disable();
00258 return;
00259 }
00260 mWallTime[event] -= GetWallTime();
00261 mHasBegun[event] = true;
00262
00263 }
00264
00270 void EndEventImpl(unsigned event)
00271 {
00272 assert(event<NUM_EVENTS);
00273 if (!mEnabled)
00274 {
00275 return;
00276 }
00277 #ifdef CHASTE_EVENT_BARRIERS
00278 PetscTools::Barrier("EndEvent");
00279 #endif
00280 if (!mHasBegun[event])
00281 {
00282 std::string msg;
00283 msg += "Error: The event associated with the counter for '";
00284 msg += CONCRETE::EventName[event];
00285 msg += "' had not begun when EndEvent was called.";
00286 EXCEPTION(msg);
00287 }
00288 mWallTime[event] += GetWallTime();
00289 mHasBegun[event] = false;
00290
00291 }
00292
00300 double GetElapsedTimeImpl(unsigned event)
00301 {
00302 assert(event<NUM_EVENTS);
00303 if (!mEnabled)
00304 {
00305 return 0.0;
00306 }
00307 double time;
00308 if (mHasBegun[event])
00309 {
00310 time = mWallTime[event] + GetWallTime();
00311 }
00312 else
00313 {
00314 time = mWallTime[event];
00315 }
00316 return ConvertWallTimeToMilliseconds(time);
00317 }
00318
00327 void ReportImpl()
00328 {
00329 if (!mEnabled)
00330 {
00331 EXCEPTION("Asked to report on a disabled event handler. Check for contributory errors above.");
00332 }
00333 if (!mInUse)
00334 {
00335 EXCEPTION("Asked to report on an event handler which is set to zero.");
00336 }
00337
00338 for (unsigned event=0; event<NUM_EVENTS; event++)
00339 {
00340 if (mHasBegun[event])
00341 {
00342
00343 EndEvent(event);
00344 }
00345 }
00346 const unsigned top_event = NUM_EVENTS-1;
00347 double total = ConvertWallTimeToSeconds(mWallTime[top_event]);
00348
00349
00350 const char* format;
00351 if (total > 999999.0)
00352 {
00353 format = "%8.0f ";
00354 }
00355 else if (total > 9999.0)
00356 {
00357 format = "%8.1f ";
00358 }
00359 else
00360 {
00361 format = "%8.3f ";
00362 }
00363
00364 PetscTools::BeginRoundRobin();
00365 {
00366 std::cout.flush();
00367 if (PetscTools::IsParallel())
00368 {
00369
00370 printf("%3i: ", PetscTools::GetMyRank());
00371 }
00372 for (unsigned event=0; event<NUM_EVENTS; event++)
00373 {
00374 const double secs = ConvertWallTimeToSeconds(mWallTime[event]);
00375 printf(format, secs);
00376 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00377 }
00378 std::cout << "(seconds) \n";
00379 }
00380 PetscTools::EndRoundRobin();
00381
00382
00383 if (PetscTools::IsParallel())
00384 {
00385 double total_cpu_time[NUM_EVENTS];
00386 MPI_Reduce(&mWallTime[0], total_cpu_time, NUM_EVENTS, MPI_DOUBLE,
00387 MPI_SUM, 0, PETSC_COMM_WORLD);
00388 if (PetscTools::AmMaster())
00389 {
00390 total = ConvertWallTimeToSeconds(total_cpu_time[top_event]);
00391 printf("avg: ");
00392 for (unsigned event=0; event<NUM_EVENTS; event++)
00393 {
00394 const double secs = ConvertWallTimeToSeconds(total_cpu_time[event]);
00395 printf(format, secs/PetscTools::GetNumProcs());
00396 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00397 }
00398 std::cout << "(seconds) \n";
00399 }
00400
00401 double max_cpu_time[NUM_EVENTS];
00402 MPI_Reduce(&mWallTime[0], max_cpu_time, NUM_EVENTS, MPI_DOUBLE,
00403 MPI_MAX, 0, PETSC_COMM_WORLD);
00404 if (PetscTools::AmMaster())
00405 {
00406 total = ConvertWallTimeToSeconds(max_cpu_time[top_event]);
00407 printf("max: ");
00408 for (unsigned event=0; event<NUM_EVENTS; event++)
00409 {
00410 const double secs = ConvertWallTimeToSeconds(max_cpu_time[event]);
00411 printf(format, secs);
00412 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00413 }
00414 std::cout << "(seconds) \n";
00415 }
00416 }
00417 std::cout.flush();
00418 PetscTools::Barrier();
00419 std::cout.flush();
00420
00421 Reset();
00422 }
00423
00427 void HeadingsImpl()
00428 {
00429
00430 std::cout.flush();
00431 PetscTools::Barrier();
00432 std::cout.flush();
00433 if (PetscTools::AmMaster())
00434 {
00435 if (PetscTools::IsParallel())
00436 {
00437
00438 printf("Proc ");
00439 }
00440 for (unsigned event=0; event<NUM_EVENTS; event++)
00441 {
00442 printf("%15s%2s", CONCRETE::EventName[event], "");
00443 }
00444 std::cout << "\n";
00445 std::cout.flush();
00446 }
00447 }
00448
00452 void EnableImpl()
00453 {
00454 mEnabled = true;
00455 }
00456
00458 void DisableImpl()
00459 {
00460 mEnabled = false;
00461 }
00462
00464 bool IsEnabledImpl()
00465 {
00466 return mEnabled;
00467 }
00468 };
00469
00470 #endif