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 private:
00056 static std::vector<double> mCpuTime;
00057 static std::vector<bool> mHasBegun;
00058 static bool mEnabled;
00059 static bool mInitialised;
00060 static bool mInUse;
00062 inline static double GetCpuTime()
00063 {
00064 return clock();
00065 }
00066
00072 inline static double ConvertTicksToMilliseconds(double clockTicks)
00073 {
00074 return clockTicks/(CLOCKS_PER_SEC/1000.0);
00075 }
00076
00082 inline static double ConvertTicksToSeconds(double clockTicks)
00083 {
00084 return clockTicks/(CLOCKS_PER_SEC);
00085 }
00086
00088 inline static void CheckVectorSizes()
00089 {
00090 if (!mInitialised)
00091 {
00092 mCpuTime.resize(NUM_EVENTS, 0.0);
00093 mHasBegun.resize(NUM_EVENTS, false);
00094 mInitialised = true;
00095 }
00096 }
00097
00098 public:
00099
00103 static void Reset()
00104 {
00105 CheckVectorSizes();
00106 for (unsigned event=0; event<NUM_EVENTS; event++)
00107 {
00108 mCpuTime[event] = 0.0;
00109 mHasBegun[event] = false;
00110 }
00111 Enable();
00112 mInUse=false;
00113 }
00114
00120 static void BeginEvent(unsigned event) throw (Exception)
00121 {
00122 if (!mEnabled)
00123 {
00124 return;
00125 }
00126 mInUse = true;
00127 assert(event<NUM_EVENTS);
00128 CheckVectorSizes();
00129
00130 if (event<NUM_EVENTS-1)
00131 {
00132 if (!mHasBegun[NUM_EVENTS-1])
00133 {
00134
00135 BeginEvent(NUM_EVENTS-1);
00136 }
00137 }
00138 if (mHasBegun[event])
00139 {
00140 std::string msg;
00141 msg += "The event associated with the counter for '";
00142 msg += CONCRETE::EventName[event];
00143 msg += "' had already begun when BeginEvent was called.";
00144 std::cerr << msg << std::endl << std::flush;
00145 Disable();
00146 return;
00147 }
00148 mCpuTime[event] -= GetCpuTime();
00149 mHasBegun[event] = true;
00150
00151 }
00152
00158 static void EndEvent(unsigned event)
00159 {
00160 assert(event<NUM_EVENTS);
00161 if (!mEnabled)
00162 {
00163 return;
00164 }
00165 CheckVectorSizes();
00166 if (!mHasBegun[event])
00167 {
00168 std::string msg;
00169 msg += "Error: The event associated with the counter for '";
00170 msg += CONCRETE::EventName[event];
00171 msg += "' had not begun when EndEvent was called.";
00172 EXCEPTION(msg);
00173 }
00174 mCpuTime[event] += GetCpuTime();
00175 mHasBegun[event] = false;
00176
00177 }
00178
00186 static double GetElapsedTime(unsigned event)
00187 {
00188 assert(event<NUM_EVENTS);
00189 if (!mEnabled)
00190 {
00191 return 0.0;
00192 }
00193 CheckVectorSizes();
00194 double ticks;
00195 if (mHasBegun[event])
00196 {
00197 ticks = mCpuTime[event] + GetCpuTime();
00198 }
00199 else
00200 {
00201 ticks = mCpuTime[event];
00202 }
00203 return ConvertTicksToMilliseconds(ticks);
00204 }
00205
00214 static void Report()
00215 {
00216 CheckVectorSizes();
00217
00218 if (!mEnabled)
00219 {
00220 EXCEPTION("Asked to report on a disabled event handler. Check for contributory errors above.");
00221 }
00222 if (!mInUse)
00223 {
00224 EXCEPTION("Asked to report on an event handler which is set to zero.");
00225 }
00226
00227 for (unsigned event=0; event<NUM_EVENTS; event++)
00228 {
00229 if (mHasBegun[event])
00230 {
00231
00232 EndEvent(event);
00233 }
00234 }
00235 const unsigned top_event = NUM_EVENTS-1;
00236 double total = ConvertTicksToSeconds(mCpuTime[top_event]);
00237
00238
00239 const char* format;
00240 if (total > 999999.0)
00241 {
00242 format = "%8.0f ";
00243 }
00244 else if (total > 9999.0)
00245 {
00246 format = "%8.1f ";
00247 }
00248 else
00249 {
00250 format = "%8.3f ";
00251 }
00252
00253 for (unsigned turn=0; turn<PetscTools::GetNumProcs(); turn++)
00254 {
00255 std::cout.flush();
00256 PetscTools::Barrier();
00257 if (turn == PetscTools::GetMyRank())
00258 {
00259 if (!PetscTools::IsSequential())
00260 {
00261
00262 printf("%3i: ", turn);
00263 }
00264 for (unsigned event=0; event<NUM_EVENTS; event++)
00265 {
00266 const double secs = ConvertTicksToSeconds(mCpuTime[event]);
00267 printf(format, secs);
00268 printf("(%3.0f%%) ", secs/total*100.0);
00269 }
00270 std::cout << "(seconds) \n";
00271 }
00272 }
00273
00274
00275 if (!PetscTools::IsSequential())
00276 {
00277 double total_cpu_time[NUM_EVENTS];
00278 MPI_Reduce(&mCpuTime[0], total_cpu_time, NUM_EVENTS, MPI_DOUBLE,
00279 MPI_SUM, 0, PETSC_COMM_WORLD);
00280 if (PetscTools::AmMaster())
00281 {
00282 total = ConvertTicksToSeconds(total_cpu_time[top_event]);
00283 printf("avg: ");
00284 for (unsigned event=0; event<NUM_EVENTS; event++)
00285 {
00286 const double secs = ConvertTicksToSeconds(total_cpu_time[event]);
00287 printf(format, secs/PetscTools::GetNumProcs());
00288 printf("(%3.0f%%) ", secs/total*100.0);
00289 }
00290 std::cout << "(seconds) \n";
00291 }
00292
00293 double max_cpu_time[NUM_EVENTS];
00294 MPI_Reduce(&mCpuTime[0], max_cpu_time, NUM_EVENTS, MPI_DOUBLE,
00295 MPI_MAX, 0, PETSC_COMM_WORLD);
00296 if (PetscTools::AmMaster())
00297 {
00298 total = ConvertTicksToSeconds(max_cpu_time[top_event]);
00299 printf("max: ");
00300 for (unsigned event=0; event<NUM_EVENTS; event++)
00301 {
00302 const double secs = ConvertTicksToSeconds(max_cpu_time[event]);
00303 printf(format, secs);
00304 printf("(%3.0f%%) ", secs/total*100.0);
00305 }
00306 std::cout << "(seconds) \n";
00307 }
00308 }
00309 std::cout.flush();
00310 PetscTools::Barrier();
00311 std::cout.flush();
00312
00313 Reset();
00314 }
00315
00319 static void Headings()
00320 {
00321 CheckVectorSizes();
00322
00323 std::cout.flush();
00324 PetscTools::Barrier();
00325 std::cout.flush();
00326 if (PetscTools::AmMaster())
00327 {
00328 if (!PetscTools::IsSequential())
00329 {
00330
00331 printf("Proc ");
00332 }
00333 for (unsigned event=0; event<NUM_EVENTS; event++)
00334 {
00335 printf("%15s%2s", CONCRETE::EventName[event], "");
00336 }
00337 std::cout << "\n";
00338 std::cout.flush();
00339 }
00340 }
00341
00345 static void Enable()
00346 {
00347 CheckVectorSizes();
00348 mEnabled = true;
00349 }
00350
00352 static void Disable()
00353 {
00354 CheckVectorSizes();
00355 mEnabled = false;
00356 }
00357
00359 static bool IsEnabled()
00360 {
00361 return mEnabled;
00362 }
00363 };
00364
00365 template<unsigned NUM_EVENTS, class CONCRETE>
00366 std::vector<double> GenericEventHandler<NUM_EVENTS, CONCRETE>::mCpuTime;
00367
00368 template<unsigned NUM_EVENTS, class CONCRETE>
00369 std::vector<bool> GenericEventHandler<NUM_EVENTS, CONCRETE>::mHasBegun;
00370
00371 template<unsigned NUM_EVENTS, class CONCRETE>
00372 bool GenericEventHandler<NUM_EVENTS, CONCRETE>::mEnabled = true;
00373
00374 template<unsigned NUM_EVENTS, class CONCRETE>
00375 bool GenericEventHandler<NUM_EVENTS, CONCRETE>::mInitialised = false;
00376
00377 template<unsigned NUM_EVENTS, class CONCRETE>
00378 bool GenericEventHandler<NUM_EVENTS, CONCRETE>::mInUse = false;
00379
00380 #endif