MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
walltime.c
Go to the documentation of this file.
1 #include <stdlib.h>
2 #include <mpi.h>
3 #include <string.h>
4 #include <stdio.h>
5 #include "walltime.h"
6 
7 #include "utils.h"
8 
9 static struct ClockTable * CT = NULL;
10 
11 static double WallTimeClock;
12 static double LastReportTime;
13 
14 static void walltime_clock_insert(const char * name);
15 static void walltime_summary_clocks(struct Clock * C, int N, int root, MPI_Comm comm);
16 static void walltime_update_parents(void);
17 static double seconds(void);
18 
19 void walltime_init(struct ClockTable * ct) {
20  CT = ct;
21  CT->Nmax = 512;
22  CT->N = 0;
23  CT->ElapsedTime = 0;
27 }
28 
29 static void walltime_summary_clocks(struct Clock * C, int N, int root, MPI_Comm comm) {
30  double * t = ta_malloc("clocks", double, 4 * N);
31  double * min = t + N;
32  double * max = t + 2 * N;
33  double * sum = t + 3 * N;
34  int i;
35  for(i = 0; i < CT->N; i ++) {
36  t[i] = C[i].time;
37  }
38  MPI_Reduce(t, min, N, MPI_DOUBLE, MPI_MIN, root, comm);
39  MPI_Reduce(t, max, N, MPI_DOUBLE, MPI_MAX, root, comm);
40  MPI_Reduce(t, sum, N, MPI_DOUBLE, MPI_SUM, root, comm);
41 
42  int NTask;
43  MPI_Comm_size(comm, &NTask);
44  /* min, max and mean are good only on process 0 */
45  for(i = 0; i < CT->N; i ++) {
46  C[i].min = min[i];
47  C[i].max = max[i];
48  C[i].mean = sum[i] / NTask;
49  }
50  ta_free(t);
51 }
52 
53 /* put min max mean of MPI ranks to rank 0*/
54 /* AC will have the total timing, C will have the current step information */
55 void walltime_summary(int root, MPI_Comm comm) {
57  int i;
58  /* add to the cumulative time */
59  for(i = 0; i < CT->N; i ++) {
60  CT->AC[i].time += CT->C[i].time;
61  }
62  walltime_summary_clocks(CT->C, CT->N, root, comm);
63  walltime_summary_clocks(CT->AC, CT->N, root, comm);
64 
65  /* clear .time for next step */
66  for(i = 0; i < CT->N; i ++) {
67  CT->C[i].time = 0;
68  }
69  MPI_Barrier(comm);
70  /* wo do this here because all processes are sync after summary_clocks*/
71  double step_all = seconds() - LastReportTime;
73  CT->ElapsedTime += step_all;
74  CT->StepTime = step_all;
75 }
76 
77 static int clockcmp(const void * c1, const void * c2) {
78  const struct Clock * p1 = (const struct Clock *) c1;
79  const struct Clock * p2 = (const struct Clock *) c2;
80  return strcmp(p1->name, p2->name);
81 }
82 
83 static void walltime_clock_insert(const char * name) {
84  if(name[0] != '/') abort();
85  if(strlen(name) > 1) {
86  char tmp[80] = {0};
87  strncpy(tmp, name, 79);
88  char * p;
89  walltime_clock("/");
90  for(p = tmp + 1; *p; p ++) {
91  if (*p == '/') {
92  *p = 0;
93  walltime_clock(tmp);
94  *p = '/';
95  }
96  }
97  }
98  if(CT->N == CT->Nmax) {
99  /* too many counters */
100  abort();
101  }
102  const int nmsz = sizeof(CT->C[CT->N].name);
103  strncpy(CT->C[CT->N].name, name, nmsz);
104  CT->C[CT->N].name[nmsz-1] = '\0';
105  strncpy(CT->AC[CT->N].name, CT->C[CT->N].name, nmsz);
106  CT->AC[CT->N].name[nmsz-1] = '\0';
107  CT->N ++;
108  qsort_openmp(CT->C, CT->N, sizeof(struct Clock), clockcmp);
109  qsort_openmp(CT->AC, CT->N, sizeof(struct Clock), clockcmp);
110 }
111 
112 int walltime_clock(const char * name) {
113  struct Clock dummy;
114  strncpy(dummy.name, name, sizeof(dummy.name));
115  dummy.name[sizeof(dummy.name)-1]='\0';
116 
117  struct Clock * rt = (struct Clock *) bsearch(&dummy, CT->C, CT->N, sizeof(struct Clock), clockcmp);
118  if(rt == NULL) {
120  rt = (struct Clock *) bsearch(&dummy, CT->C, CT->N, sizeof(struct Clock), clockcmp);
121  }
122  return rt - CT->C;
123 };
124 
125 char walltime_get_symbol(const char * name) {
126  int id = walltime_clock(name);
127  return CT->C[id].symbol;
128 }
129 
130 double walltime_get(const char * name, enum clocktype type) {
131  int id = walltime_clock(name);
132  /* only make sense on root */
133  switch(type) {
134  case CLOCK_STEP_MEAN:
135  return CT->C[id].mean;
136  case CLOCK_STEP_MIN:
137  return CT->C[id].min;
138  case CLOCK_STEP_MAX:
139  return CT->C[id].max;
140  case CLOCK_ACCU_MEAN:
141  return CT->AC[id].mean;
142  case CLOCK_ACCU_MIN:
143  return CT->AC[id].min;
144  case CLOCK_ACCU_MAX:
145  return CT->AC[id].max;
146  }
147  return 0;
148 }
149 double walltime_get_time(const char * name) {
150  int id = walltime_clock(name);
151  return CT->C[id].time;
152 }
153 
154 static void walltime_update_parents() {
155  /* returns the sum of every clock with the same prefix */
156  int i = 0;
157  for(i = 0; i < CT->N; i ++) {
158  CT->Nchildren[i] = 0;
159  int j;
160  char * prefix = CT->C[i].name;
161  int l = strlen(prefix);
162  double t = 0;
163  for(j = i + 1; j < CT->N; j++) {
164  if(0 == strncmp(prefix, CT->C[j].name, l)) {
165  t += CT->C[j].time;
166  CT->Nchildren[i] ++;
167  } else {
168  break;
169  }
170  }
171  /* update only if there are children */
172  if (t > 0) CT->C[i].time = t;
173  }
174 }
175 
178 }
179 
180 double walltime_add_internal(const char * name, const double dt) {
181  int id = walltime_clock(name);
182  CT->C[id].time += dt;
183  return dt;
184 }
185 double walltime_measure_internal(const char * name) {
186  double t = seconds();
187  double dt = t - WallTimeClock;
189  if(name[0] != '.') {
190  int id = walltime_clock(name);
191  CT->C[id].time += dt;
192  }
193  return dt;
194 }
195 double walltime_measure_full(const char * name, const char * file, const int line) {
196  char fullname[128] = {0};
197  const char * basename = file + strlen(file);
198  while(basename >= file && *basename != '/') basename --;
199  basename ++;
200  sprintf(fullname, "%s@%s:%04d", name, basename, line);
201  return walltime_measure_internal(fullname);
202 }
203 double walltime_add_full(const char * name, const double dt, const char * file, const int line) {
204  char fullname[128] = {0};
205  const char * basename = file + strlen(file);
206  while(basename >= file && *basename != '/') basename --;
207  basename ++;
208  sprintf(fullname, "%s@%s:%04d", name, basename, line);
209  return walltime_add_internal(fullname, dt);
210 
211 }
212 
213 /* returns the number of cpu-ticks in seconds that
214  * have elapsed. (or the wall-clock time)
215  */
216 static double seconds(void)
217 {
218  return MPI_Wtime();
219 }
220 void walltime_report(FILE * fp, int root, MPI_Comm comm) {
221  int rank;
222  MPI_Comm_rank(comm, &rank);
223  if(rank != root) return;
224  int i;
225  for(i = 0; i < CT->N; i ++) {
226  char * name = CT->C[i].name;
227  int level = 0;
228  char * p = name;
229  while(*p) {
230  if(*p == '/') {
231  level ++;
232  name = p + 1;
233  }
234  p++;
235  }
236  /* if there is just one child, don't print it*/
237  if(CT->Nchildren[i] == 1) continue;
238  fprintf(fp, "%*s%-26s %10.2f %4.1f%% %10.2f %4.1f%% %10.2f %10.2f\n",
239  level, "", /* indents */
240  name, /* just the last seg of name*/
241  CT->AC[i].mean,
242  CT->AC[i].mean / CT->ElapsedTime * 100.,
243  CT->C[i].mean,
244  CT->C[i].mean / CT->StepTime * 100.,
245  CT->C[i].min,
246  CT->C[i].max
247  );
248  }
249 }
250 #if 0
251 #define HELLO atom(&atomtable, "Hello")
252 #define WORLD atom(&atomtable, "WORLD")
253 int main() {
254  walltime_init();
255  printf("%d\n", HELLO, atom_name(&atomtable, HELLO));
256  printf("%d\n", HELLO, atom_name(&atomtable, HELLO));
257  printf("%d\n", WORLD, atom_name(&atomtable, WORLD));
258  printf("%d\n", HELLO, atom_name(&atomtable, HELLO));
259 }
260 #endif
const char * name
Definition: densitykernel.c:93
#define ta_malloc(name, type, nele)
Definition: mymalloc.h:25
#define ta_free(p)
Definition: mymalloc.h:28
double StepTime
Definition: walltime.h:55
double ElapsedTime
Definition: walltime.h:54
int Nchildren[512]
Definition: walltime.h:53
struct Clock AC[512]
Definition: walltime.h:52
struct Clock C[512]
Definition: walltime.h:51
int Nmax
Definition: walltime.h:49
Definition: walltime.h:39
double max
Definition: walltime.h:42
char symbol
Definition: walltime.h:45
double mean
Definition: walltime.h:44
char name[128]
Definition: walltime.h:40
double min
Definition: walltime.h:43
double time
Definition: walltime.h:41
int main(void)
Definition: test_cooling.c:243
int NTask
Definition: test_exchange.c:23
#define qsort_openmp
Definition: test_exchange.c:14
char prefix[1024]
Definition: test_hci.c:13
void walltime_init(struct ClockTable *ct)
Definition: walltime.c:19
static double WallTimeClock
Definition: walltime.c:11
static void walltime_update_parents(void)
Definition: walltime.c:154
static void walltime_clock_insert(const char *name)
Definition: walltime.c:83
int walltime_clock(const char *name)
Definition: walltime.c:112
void walltime_summary(int root, MPI_Comm comm)
Definition: walltime.c:55
double walltime_measure_internal(const char *name)
Definition: walltime.c:185
double walltime_add_full(const char *name, const double dt, const char *file, const int line)
Definition: walltime.c:203
static int clockcmp(const void *c1, const void *c2)
Definition: walltime.c:77
static double seconds(void)
Definition: walltime.c:216
double walltime_measure_full(const char *name, const char *file, const int line)
Definition: walltime.c:195
double walltime_get_time(const char *name)
Definition: walltime.c:149
double walltime_get(const char *name, enum clocktype type)
Definition: walltime.c:130
static double LastReportTime
Definition: walltime.c:12
double walltime_add_internal(const char *name, const double dt)
Definition: walltime.c:180
char walltime_get_symbol(const char *name)
Definition: walltime.c:125
void walltime_report(FILE *fp, int root, MPI_Comm comm)
Definition: walltime.c:220
void walltime_reset()
Definition: walltime.c:176
static void walltime_summary_clocks(struct Clock *C, int N, int root, MPI_Comm comm)
Definition: walltime.c:29
static struct ClockTable * CT
Definition: walltime.c:9
clocktype
Definition: walltime.h:15
@ CLOCK_STEP_MAX
Definition: walltime.h:17
@ CLOCK_ACCU_MIN
Definition: walltime.h:21
@ CLOCK_STEP_MEAN
Definition: walltime.h:16
@ CLOCK_STEP_MIN
Definition: walltime.h:18
@ CLOCK_ACCU_MAX
Definition: walltime.h:20
@ CLOCK_ACCU_MEAN
Definition: walltime.h:19