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
00047 template <unsigned NUM_EVENTS, class CONCRETE>
00048 class GenericEventHandler
00049 {
00050 private:
00051 static std::vector<double> mCpuTime;
00052 static std::vector<bool> mHasBegun;
00053 static bool mEnabled;
00054 static bool mInitialised;
00057 inline static double GetCpuTime()
00058 {
00059 return clock();
00060 }
00061
00067 inline static double ConvertTicksToMilliseconds(double clockTicks)
00068 {
00069 return clockTicks/(CLOCKS_PER_SEC/1000.0);
00070 }
00071
00077 inline static double ConvertTicksToSeconds(double clockTicks)
00078 {
00079 return clockTicks/(CLOCKS_PER_SEC);
00080 }
00081
00083 inline static void CheckVectorSizes()
00084 {
00085 if (!mInitialised)
00086 {
00087 mCpuTime.resize(NUM_EVENTS, 0.0);
00088 mHasBegun.resize(NUM_EVENTS, false);
00089 mInitialised = true;
00090 }
00091 }
00092
00093 public:
00094
00098 static void Reset()
00099 {
00100 CheckVectorSizes();
00101 for (unsigned event=0; event<NUM_EVENTS; event++)
00102 {
00103 mCpuTime[event] = 0.0;
00104 mHasBegun[event] = false;
00105 }
00106 Enable();
00107 }
00108
00114 static void BeginEvent(unsigned event) throw (Exception)
00115 {
00116 assert(event<NUM_EVENTS);
00117 if (!mEnabled)
00118 {
00119 return;
00120 }
00121 CheckVectorSizes();
00122 if (mHasBegun[event])
00123 {
00124 std::string msg;
00125 msg += "The event associated with the counter for '";
00126 msg += CONCRETE::EventName[event];
00127 msg += "' had already begun when BeginEvent was called.";
00128 std::cerr << msg << std::endl << std::flush;
00129 Disable();
00130 return;
00131 }
00132 mCpuTime[event] -= GetCpuTime();
00133 mHasBegun[event] = true;
00134
00135 }
00136
00142 static void EndEvent(unsigned event)
00143 {
00144 assert(event<NUM_EVENTS);
00145 if (!mEnabled)
00146 {
00147 return;
00148 }
00149 CheckVectorSizes();
00150 if (!mHasBegun[event])
00151 {
00152 std::string msg;
00153 msg += "Error: The event associated with the counter for '";
00154 msg += CONCRETE::EventName[event];
00155 msg += "' had not begun when EndEvent was called.";
00156 EXCEPTION(msg);
00157 }
00158 mCpuTime[event] += GetCpuTime();
00159 mHasBegun[event] = false;
00160
00161 }
00162
00170 static double GetElapsedTime(unsigned event)
00171 {
00172 assert(event<NUM_EVENTS);
00173 if (!mEnabled)
00174 {
00175 return 0.0;
00176 }
00177 CheckVectorSizes();
00178 double ticks;
00179 if (mHasBegun[event])
00180 {
00181 ticks = mCpuTime[event] + GetCpuTime();
00182 }
00183 else
00184 {
00185 ticks = mCpuTime[event];
00186 }
00187 return ConvertTicksToMilliseconds(ticks);
00188 }
00189
00198 static void Report()
00199 {
00200 CheckVectorSizes();
00201
00202 if (!mEnabled)
00203 {
00204 EXCEPTION("Asked to report on a disabled event handler. Check for contributory errors above.");
00205 }
00206
00207 const unsigned top_event = NUM_EVENTS-1;
00208 double total = ConvertTicksToSeconds(mCpuTime[top_event]);
00209 for (unsigned turn=0; turn<PetscTools::NumProcs(); turn++)
00210 {
00211 std::cout.flush();
00212 PetscTools::Barrier();
00213 if (turn == PetscTools::GetMyRank())
00214 {
00215 if (!PetscTools::IsSequential())
00216 {
00217
00218 printf("%3i: ", turn);
00219 }
00220 for (unsigned event=0; event<NUM_EVENTS; event++)
00221 {
00222 const double secs = ConvertTicksToSeconds(mCpuTime[event]);
00223 printf("%7.2e ", secs);
00224 printf("(%3.0f%%) ", secs/total*100.0);
00225 }
00226 std::cout << "(seconds) \n";
00227 }
00228 }
00229
00230
00231 if (!PetscTools::IsSequential())
00232 {
00233 double total_cpu_time[NUM_EVENTS];
00234 MPI_Reduce(&mCpuTime[0], total_cpu_time, NUM_EVENTS, MPI_DOUBLE,
00235 MPI_SUM, 0, PETSC_COMM_WORLD);
00236 if (PetscTools::AmMaster())
00237 {
00238 total = ConvertTicksToSeconds(total_cpu_time[top_event]);
00239 printf("avg: ");
00240 for (unsigned event=0; event<NUM_EVENTS; event++)
00241 {
00242 const double secs = ConvertTicksToSeconds(total_cpu_time[event]);
00243 printf("%7.2e ", secs/PetscTools::NumProcs());
00244 printf("(%3.0f%%) ", secs/total*100.0);
00245 }
00246 std::cout << "(seconds) \n";
00247 }
00248
00249 double max_cpu_time[NUM_EVENTS];
00250 MPI_Reduce(&mCpuTime[0], max_cpu_time, NUM_EVENTS, MPI_DOUBLE,
00251 MPI_MAX, 0, PETSC_COMM_WORLD);
00252 if (PetscTools::AmMaster())
00253 {
00254 total = ConvertTicksToSeconds(max_cpu_time[top_event]);
00255 printf("max: ");
00256 for (unsigned event=0; event<NUM_EVENTS; event++)
00257 {
00258 const double secs = ConvertTicksToSeconds(max_cpu_time[event]);
00259 printf("%7.2e ", secs);
00260 printf("(%3.0f%%) ", secs/total*100.0);
00261 }
00262 std::cout << "(seconds) \n";
00263 }
00264 }
00265 std::cout.flush();
00266 PetscTools::Barrier();
00267 std::cout.flush();
00268
00269 Reset();
00270 }
00271
00275 static void Headings()
00276 {
00277 CheckVectorSizes();
00278
00279 std::cout.flush();
00280 PetscTools::Barrier();
00281 std::cout.flush();
00282 if (PetscTools::AmMaster())
00283 {
00284 if (!PetscTools::IsSequential())
00285 {
00286
00287 printf("Proc ");
00288 }
00289 for (unsigned event=0; event<NUM_EVENTS; event++)
00290 {
00291 printf("%15s%2s", CONCRETE::EventName[event], "");
00292 }
00293 std::cout << "\n";
00294 std::cout.flush();
00295 }
00296 }
00297
00301 static void Enable()
00302 {
00303 CheckVectorSizes();
00304 mEnabled = true;
00305 }
00306
00308 static void Disable()
00309 {
00310 CheckVectorSizes();
00311 mEnabled = false;
00312 }
00313
00315 static bool IsEnabled()
00316 {
00317 return mEnabled;
00318 }
00319 };
00320
00321 template<unsigned NUM_EVENTS, class CONCRETE>
00322 std::vector<double> GenericEventHandler<NUM_EVENTS, CONCRETE>::mCpuTime;
00323
00324 template<unsigned NUM_EVENTS, class CONCRETE>
00325 std::vector<bool> GenericEventHandler<NUM_EVENTS, CONCRETE>::mHasBegun;
00326
00327 template<unsigned NUM_EVENTS, class CONCRETE>
00328 bool GenericEventHandler<NUM_EVENTS, CONCRETE>::mEnabled = true;
00329
00330 template<unsigned NUM_EVENTS, class CONCRETE>
00331 bool GenericEventHandler<NUM_EVENTS, CONCRETE>::mInitialised = false;
00332
00333 #endif