00001
00002
00003
00004
00005
00006
00007 #ifndef ADLIB_TIMING_H
00008 #define ADLIB_TIMING_H
00009
00017 #include <iostream>
00018 #include <vector>
00019
00020 #ifndef WITH_MPI
00021
00022 #include <sys/time.h>
00023 #include <time.h>
00024 inline static double MPI_Wtime() {
00025 struct timeval t;
00026 gettimeofday(&t,0);
00027 return (double)t.tv_sec + ((double)t.tv_usec)*0.000001;
00028 }
00029
00030 #endif
00031
00032 class AdlibTiming;
00033 extern AdlibTiming adlib_timing;
00034
00035 #ifdef TIMING_ADLIB
00036
00037 #define ADLIB_START_WATCH adlib_timing.start();
00038 #define ADLIB_END_WATCH(what) adlib_timing.stop(AdlibTiming::what);
00039
00040 #define ADLIB_START_WATCH_WHOLE adlib_timing.start_timing();
00041 #define ADLIB_END_WATCH_WHOLE adlib_timing.stop(AdlibTiming::MISC);
00042
00043 #else
00044
00045 #define ADLIB_START_WATCH_WHOLE
00046 #define ADLIB_START_WATCH
00047 #define ADLIB_END_WATCH(what)
00048 #define ADLIB_END_WATCH_WHOLE
00049
00050 #endif
00051
00059 class AdlibTiming {
00060 public:
00064 enum TimingAccounts {
00065 WHOLE,
00066
00067 MISC,
00068
00069
00070 INITIALIZATION, INTEGRATION, ASSEMBLE, OUTPUT,
00071 EXAMINE1, EXAMINE2, EXAMINE3, EXAMINE4,
00072
00073 ELC_SNDBND_RCVPRS,
00074
00075 CPL_SEND_OVERHEAD, CPL_RECEIVE_OVERHEAD,
00076
00077
00078 _ACMAX };
00079
00080 public:
00081
00082
00083
00086 inline void start_timing()
00087 { tos = ×tack[0]; *tos = 0.0; start_time = MPI_Wtime(); }
00088
00091 inline void start() { add_time(); tos++; *tos = 0.0; }
00092
00096 inline void stop(enum TimingAccounts account)
00097 { add_time(); times[account] += *tos; calls[account]++; tos--; }
00098
00099 protected:
00100 inline void add_time() {
00101 double end_time = MPI_Wtime();
00102 *tos += end_time - start_time; start_time = end_time;
00103 }
00104
00105 public:
00106
00107
00108
00111 static void collect(MPI_Comm Comm) {
00112 #ifdef TIMING_ADLIB
00113 adlib_timing.collect_timing(Comm);
00114 #endif
00115 }
00116
00117 static void print(std::ostream& os) {
00118 #ifdef TIMING_ADLIB
00119 adlib_timing.print_local_times = false;
00120 adlib_timing.print_timing(os);
00121 #endif
00122 }
00123
00124 static void print_local(std::ostream& os) {
00125 #ifdef TIMING_ADLIB
00126 adlib_timing.print_local_times = true;
00127 adlib_timing.print_timing(os);
00128 #endif
00129 }
00130
00133 void collect_timing(MPI_Comm Comm, enum TimingAccounts ac,
00134 double* stat_times) {
00135 #ifdef WITH_MPI
00136 MPI_Reduce(×[ac], &stat_times[0], 1, MPI_DOUBLE,
00137 MPI_MAX, 0, Comm);
00138 MPI_Reduce(×[ac], &stat_times[1], 1, MPI_DOUBLE,
00139 MPI_MIN, 0, Comm);
00140 MPI_Reduce(×[ac], &stat_times[2], 1, MPI_DOUBLE,
00141 MPI_SUM, 0, Comm);
00142
00143 int procs;
00144 MPI_Comm_size(Comm, &procs);
00145 stat_times[2] /= procs;
00146 #else
00147 stat_times[0] = times[ac];
00148 stat_times[1] = times[ac];
00149 stat_times[2] = times[ac];
00150 #endif
00151 }
00152
00155 void collect_timing(MPI_Comm Comm) {
00156
00157 times[WHOLE] = calcsum(times, MISC, _ACMAX-1, 0.0);
00158 calls[WHOLE] = calcsum(calls, MISC, _ACMAX-1, (unsigned)0);
00159
00160
00161 stat_times_max.resize(_ACMAX);
00162 stat_times_min.resize(_ACMAX);
00163 stat_times_avg.resize(_ACMAX);
00164 #ifdef WITH_MPI
00165 MPI_Reduce(×[0], &stat_times_max[0], _ACMAX, MPI_DOUBLE,
00166 MPI_MAX, 0, Comm);
00167 MPI_Reduce(×[0], &stat_times_min[0], _ACMAX, MPI_DOUBLE,
00168 MPI_MIN, 0, Comm);
00169 MPI_Reduce(×[0], &stat_times_avg[0], _ACMAX, MPI_DOUBLE,
00170 MPI_SUM, 0, Comm);
00171
00172 int procs;
00173 MPI_Comm_size(Comm, &procs);
00174 for (int i=0; i<_ACMAX; i++)
00175 stat_times_avg[i] /= procs;
00176 #else
00177 stat_times_max = times;
00178 stat_times_min = times;
00179 stat_times_avg = times;
00180 #endif
00181 }
00182
00186 void print_timing(std::ostream& os) {
00187 pl(os,"Initialization ", INITIALIZATION);
00188 pl(os,"Integration ", INTEGRATION);
00189 pl(os,"Assemble ", ASSEMBLE);
00190 pl(os,"ELC - sendrcv_() ", ELC_SNDBND_RCVPRS,true);
00191 pl(os,"Coupling Send - Overhead ", CPL_SEND_OVERHEAD,true);
00192 pl(os,"Coupling Receive - Overhead ", CPL_RECEIVE_OVERHEAD,true);
00193 pl(os,"Output ", OUTPUT);
00194 pl(os,"Examined in detail 1 ", EXAMINE1,true);
00195 pl(os,"Examined in detail 2 ", EXAMINE2,true);
00196 pl(os,"Examined in detail 3 ", EXAMINE3,true);
00197 pl(os,"Examined in detail 4 ", EXAMINE4,true);
00198 pl(os,"Misc ", MISC);
00199 pl(os,"Whole time ", WHOLE);
00200 }
00201
00202 protected:
00206 template<typename T>
00207 inline T calcsum(typename std::vector<T> &data,
00208 int start, int end, T sum) {
00209 for (int i=start; i<=end; i++) sum += data[i];
00210 return sum;
00211 }
00212
00215 inline void pl(std::ostream& OS, char *name,
00216 enum TimingAccounts ac, bool opt=false) {
00217 char str[500];
00218 if (print_local_times) {
00219 if (opt && times[ac]==0.) return;
00220 std::sprintf(str, " %s : %4.3fs (%3.2f%%) calls: %4ix",
00221 name,
00222 times[ac], (times[WHOLE]>0. ? 100.0*times[ac]/times[WHOLE] : 0.),
00223 calls[ac]
00224 );
00225 } else {
00226 if (opt && stat_times_avg[ac]==0.) return;
00227 std::sprintf(str, " %s : %4.3fs (%3.2f%%) balance: %2.3f diff: %4.2fs (%9.2fs - %4.2fs)",
00228 name,
00229 stat_times_avg[ac], (stat_times_avg[WHOLE]>0. ?
00230 100.0*stat_times_avg[ac]/stat_times_avg[WHOLE] : 0.),
00231 (stat_times_avg[ac]>0. ? stat_times_max[ac] / stat_times_avg[ac] : 1.),
00232 stat_times_max[ac] - stat_times_min[ac],
00233 stat_times_max[ac], stat_times_min[ac]
00234 );
00235 }
00236 OS << str << std::endl;
00237 }
00238
00239 public:
00240 AdlibTiming() {
00241 times.resize(_ACMAX, 0.0);
00242 calls.resize(_ACMAX, 0);
00243 timestack.resize(MAXRECURSIONS);
00244 }
00245
00246 protected:
00247 std::vector<double> times;
00248 std::vector<unsigned int> calls;
00249
00250 enum {MAXRECURSIONS=300};
00251 std::vector<double> timestack;
00252 double *tos;
00253
00255 bool print_local_times;
00256 std::vector<double> stat_times_max;
00257 std::vector<double> stat_times_min;
00258 std::vector<double> stat_times_avg;
00259
00260 double start_time;
00261 };
00262
00263 #endif
00264