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 #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> mCpuTime;
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 = clock();
00075 double min_ticks = milliseconds*(CLOCKS_PER_SEC/1000.0) + start;
00076 while (clock() < min_ticks)
00077 {
00078
00079 }
00080 }
00081
00083 inline static double GetCpuTime()
00084 {
00085 return clock();
00086 }
00087
00093 inline static double ConvertTicksToMilliseconds(double clockTicks)
00094 {
00095 return clockTicks/(CLOCKS_PER_SEC/1000.0);
00096 }
00097
00103 inline static double ConvertTicksToSeconds(double clockTicks)
00104 {
00105 return clockTicks/(CLOCKS_PER_SEC);
00106 }
00107
00109 inline static void CheckVectorSizes()
00110 {
00111 if (!mInitialised)
00112 {
00113 mCpuTime.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 mCpuTime[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 mInUse = true;
00148 assert(event<NUM_EVENTS);
00149 CheckVectorSizes();
00150
00151 if (event<NUM_EVENTS-1)
00152 {
00153 if (!mHasBegun[NUM_EVENTS-1])
00154 {
00155
00156 BeginEvent(NUM_EVENTS-1);
00157 }
00158 }
00159 if (mHasBegun[event])
00160 {
00161 std::string msg;
00162 msg += "The event associated with the counter for '";
00163 msg += CONCRETE::EventName[event];
00164 msg += "' had already begun when BeginEvent was called.";
00165 std::cerr << msg << std::endl << std::flush;
00166 Disable();
00167 return;
00168 }
00169 mCpuTime[event] -= GetCpuTime();
00170 mHasBegun[event] = true;
00171
00172 }
00173
00179 static void EndEvent(unsigned event)
00180 {
00181 assert(event<NUM_EVENTS);
00182 if (!mEnabled)
00183 {
00184 return;
00185 }
00186 CheckVectorSizes();
00187 if (!mHasBegun[event])
00188 {
00189 std::string msg;
00190 msg += "Error: The event associated with the counter for '";
00191 msg += CONCRETE::EventName[event];
00192 msg += "' had not begun when EndEvent was called.";
00193 EXCEPTION(msg);
00194 }
00195 mCpuTime[event] += GetCpuTime();
00196 mHasBegun[event] = false;
00197
00198 }
00199
00207 static double GetElapsedTime(unsigned event)
00208 {
00209 assert(event<NUM_EVENTS);
00210 if (!mEnabled)
00211 {
00212 return 0.0;
00213 }
00214 CheckVectorSizes();
00215 double ticks;
00216 if (mHasBegun[event])
00217 {
00218 ticks = mCpuTime[event] + GetCpuTime();
00219 }
00220 else
00221 {
00222 ticks = mCpuTime[event];
00223 }
00224 return ConvertTicksToMilliseconds(ticks);
00225 }
00226
00235 static void Report()
00236 {
00237 CheckVectorSizes();
00238
00239 if (!mEnabled)
00240 {
00241 EXCEPTION("Asked to report on a disabled event handler. Check for contributory errors above.");
00242 }
00243 if (!mInUse)
00244 {
00245 EXCEPTION("Asked to report on an event handler which is set to zero.");
00246 }
00247
00248 for (unsigned event=0; event<NUM_EVENTS; event++)
00249 {
00250 if (mHasBegun[event])
00251 {
00252
00253 EndEvent(event);
00254 }
00255 }
00256 const unsigned top_event = NUM_EVENTS-1;
00257 double total = ConvertTicksToSeconds(mCpuTime[top_event]);
00258
00259
00260 const char* format;
00261 if (total > 999999.0)
00262 {
00263 format = "%8.0f ";
00264 }
00265 else if (total > 9999.0)
00266 {
00267 format = "%8.1f ";
00268 }
00269 else
00270 {
00271 format = "%8.3f ";
00272 }
00273
00274 for (unsigned turn=0; turn<PetscTools::GetNumProcs(); turn++)
00275 {
00276 std::cout.flush();
00277 PetscTools::Barrier();
00278 if (turn == PetscTools::GetMyRank())
00279 {
00280 if (!PetscTools::IsSequential())
00281 {
00282
00283 printf("%3i: ", turn);
00284 }
00285 for (unsigned event=0; event<NUM_EVENTS; event++)
00286 {
00287 const double secs = ConvertTicksToSeconds(mCpuTime[event]);
00288 printf(format, secs);
00289 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00290 }
00291 std::cout << "(seconds) \n";
00292 }
00293 }
00294
00295
00296 if (!PetscTools::IsSequential())
00297 {
00298 double total_cpu_time[NUM_EVENTS];
00299 MPI_Reduce(&mCpuTime[0], total_cpu_time, NUM_EVENTS, MPI_DOUBLE,
00300 MPI_SUM, 0, PETSC_COMM_WORLD);
00301 if (PetscTools::AmMaster())
00302 {
00303 total = ConvertTicksToSeconds(total_cpu_time[top_event]);
00304 printf("avg: ");
00305 for (unsigned event=0; event<NUM_EVENTS; event++)
00306 {
00307 const double secs = ConvertTicksToSeconds(total_cpu_time[event]);
00308 printf(format, secs/PetscTools::GetNumProcs());
00309 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00310 }
00311 std::cout << "(seconds) \n";
00312 }
00313
00314 double max_cpu_time[NUM_EVENTS];
00315 MPI_Reduce(&mCpuTime[0], max_cpu_time, NUM_EVENTS, MPI_DOUBLE,
00316 MPI_MAX, 0, PETSC_COMM_WORLD);
00317 if (PetscTools::AmMaster())
00318 {
00319 total = ConvertTicksToSeconds(max_cpu_time[top_event]);
00320 printf("max: ");
00321 for (unsigned event=0; event<NUM_EVENTS; event++)
00322 {
00323 const double secs = ConvertTicksToSeconds(max_cpu_time[event]);
00324 printf(format, secs);
00325 printf("(%3.0f%%) ", total == 0.0 ? 0.0 : (secs/total*100.0));
00326 }
00327 std::cout << "(seconds) \n";
00328 }
00329 }
00330 std::cout.flush();
00331 PetscTools::Barrier();
00332 std::cout.flush();
00333
00334 Reset();
00335 }
00336
00340 static void Headings()
00341 {
00342 CheckVectorSizes();
00343
00344 std::cout.flush();
00345 PetscTools::Barrier();
00346 std::cout.flush();
00347 if (PetscTools::AmMaster())
00348 {
00349 if (!PetscTools::IsSequential())
00350 {
00351
00352 printf("Proc ");
00353 }
00354 for (unsigned event=0; event<NUM_EVENTS; event++)
00355 {
00356 printf("%15s%2s", CONCRETE::EventName[event], "");
00357 }
00358 std::cout << "\n";
00359 std::cout.flush();
00360 }
00361 }
00362
00366 static void Enable()
00367 {
00368 CheckVectorSizes();
00369 mEnabled = true;
00370 }
00371
00373 static void Disable()
00374 {
00375 CheckVectorSizes();
00376 mEnabled = false;
00377 }
00378
00380 static bool IsEnabled()
00381 {
00382 return mEnabled;
00383 }
00384 };
00385
00386 template<unsigned NUM_EVENTS, class CONCRETE>
00387 std::vector<double> GenericEventHandler<NUM_EVENTS, CONCRETE>::mCpuTime;
00388
00389 template<unsigned NUM_EVENTS, class CONCRETE>
00390 std::vector<bool> GenericEventHandler<NUM_EVENTS, CONCRETE>::mHasBegun;
00391
00392 template<unsigned NUM_EVENTS, class CONCRETE>
00393 bool GenericEventHandler<NUM_EVENTS, CONCRETE>::mEnabled = true;
00394
00395 template<unsigned NUM_EVENTS, class CONCRETE>
00396 bool GenericEventHandler<NUM_EVENTS, CONCRETE>::mInitialised = false;
00397
00398 template<unsigned NUM_EVENTS, class CONCRETE>
00399 bool GenericEventHandler<NUM_EVENTS, CONCRETE>::mInUse = false;
00400
00401 #endif