Cyclops Tensor Framework
parallel arithmetic on multidimensional arrays
int_timer.cxx
Go to the documentation of this file.
1 //#include <mpi.h>
2 //#include <stdio.h>
3 //#include <stdlib.h>
4 //#include <algorithm>
5 //#include <time.h>
6 //#include "string.h"
7 //#include <assert.h>
8 //#include <iostream>
9 //#include <vector>
10 #include "util.h"
11 #include "int_timer.h"
12 #include "model.h"
13 #include "../interface/timer.h"
14 
15 using namespace CTF_int;
16 
17 namespace CTF{
18  #define MAX_TOT_SYMBOLS_LEN 1000000
19 
20  int main_argc = 0;
21  const char * const * main_argv;
22  MPI_Comm comm;
23  double excl_time;
24  double complete_time;
25  int set_contxt = 0;
27 
28  Function_timer::Function_timer(char const * name_,
29  double const start_time_,
30  double const start_excl_time_){
31  ASSERT(strlen(name_)+1 < MAX_NAME_LENGTH);
32  //name = (char*)CTF_int::alloc(strlen(name_)+1);
33  //snprintf(name, MAX_NAME_LENGTH, "%s", name_);
34  strcpy(name, name_);
35  start_time = start_time_;
36  start_excl_time = start_excl_time_;
37  acc_time = 0.0;
38  acc_excl_time = 0.0;
39  calls = 0;
40  }
41 
42 /*
43  Function_timer::Function_timer(Function_timer const & other){
44  start_time = other.start_time;
45  start_excl_time = other.start_excl_time;
46  acc_time = other.acc_time;
47  calls = other.calls;
48  total_time = other.total_time;
49  total_excl_time = other.total_excl_time;
50  total_calls = other.total_calls;
51 
52  name = (char*)CTF_int::alloc(strlen(other.name)+1);
53  strcpy(name, other.name);
54 
55  }
56 
57  Function_timer::~Function_timer(){
58  cdealloc(name);
59  }
60 */
61  void Function_timer::compute_totals(MPI_Comm comm){
62  PMPI_Allreduce(&acc_time, &total_time, 1,
63  MPI_DOUBLE, MPI_SUM, comm);
64  PMPI_Allreduce(&acc_excl_time, &total_excl_time, 1,
65  MPI_DOUBLE, MPI_SUM, comm);
66  PMPI_Allreduce(&calls, &total_calls, 1,
67  MPI_INT, MPI_SUM, comm);
68  }
69 
71  return total_time > w.total_time;
72  }
73 
74  void Function_timer::print(FILE * output,
75  MPI_Comm const comm,
76  int const rank,
77  int const np){
78  int i;
79  if (rank == 0){
80  fprintf(output, "%s", name);
81  char * space = (char*)CTF_int::alloc(MAX_NAME_LENGTH-strlen(name)+1);
82  for (i=0; i<MAX_NAME_LENGTH-(int)strlen(name); i++){
83  space[i] = ' ';
84  }
85  space[i] = '\0';
86  fprintf(output, "%s", space);
87  fprintf(output,"%5d %3d.%03d %3d.%02d %3d.%03d %3d.%02d\n",
88  total_calls/np,
89  (int)(total_time/np),
90  ((int)(1000.*(total_time)/np))%1000,
91  (int)(100.*(total_time)/complete_time),
92  ((int)(10000.*(total_time)/complete_time))%100,
93  (int)(total_excl_time/np),
94  ((int)(1000.*(total_excl_time)/np))%1000,
95  (int)(100.*(total_excl_time)/complete_time),
96  ((int)(10000.*(total_excl_time)/complete_time))%100);
97  CTF_int::cdealloc(space);
98  }
99  }
100 
101  bool comp_name(Function_timer const & w1, Function_timer const & w2) {
102  return strcmp(w1.name, w2.name)>0;
103  }
104 
105  static std::vector<Function_timer> * function_timers = NULL;
106 
107  Timer::Timer(const char * name){
108  #ifdef PROFILE
109  int i;
110  if (function_timers == NULL) {
111  if (name[0] == 'M' && name[1] == 'P' &&
112  name[2] == 'I' && name[3] == '_'){
113  exited = 2;
114  original = 0;
115  return;
116  }
117  original = 1;
118  index = 0;
119  excl_time = 0.0;
120  function_timers = new std::vector<Function_timer>();
121  function_timers->push_back(Function_timer(name, MPI_Wtime(), 0.0));
122  } else {
123  for (i=0; i<(int)function_timers->size(); i++){
124  if (strcmp((*function_timers)[i].name, name) == 0){
125  /*(*function_timers)[i].start_time = MPI_Wtime();
126  (*function_timers)[i].start_excl_time = excl_time;*/
127  break;
128  }
129  }
130  index = i;
131  original = (index==0);
132  }
133  if (index == (int)function_timers->size()) {
134  function_timers->push_back(Function_timer(name, MPI_Wtime(), excl_time));
135  }
136  timer_name = name;
137  exited = 0;
138  #endif
139  }
140 
141  void Timer::start(){
142  #ifdef PROFILE
143  if (exited != 2){
144  exited = 0;
145  (*function_timers)[index].start_time = MPI_Wtime();
146  (*function_timers)[index].start_excl_time = excl_time;
147  }
148  #endif
149  }
150 
151  void Timer::stop(){
152  #ifdef PROFILE
153  if (exited == 0){
154  int is_fin;
155  MPI_Finalized(&is_fin);
156  if (!is_fin){
157  double delta_time = MPI_Wtime() - (*function_timers)[index].start_time;
158  (*function_timers)[index].acc_time += delta_time;
159  (*function_timers)[index].acc_excl_time += delta_time -
160  (excl_time- (*function_timers)[index].start_excl_time);
161  excl_time = (*function_timers)[index].start_excl_time + delta_time;
162  (*function_timers)[index].calls++;
163  }
164  exit();
165  exited = 1;
166  }
167  #endif
168  }
169 
171 
172  void print_timers(char const * name){
173  int rank, np, i, j, len_symbols, nrecv_symbols;
174 
175  int is_fin = 0;
176  MPI_Finalized(&is_fin);
177  if (is_fin) return;
178  MPI_Comm_rank(comm, &rank);
179  MPI_Comm_size(comm, &np);
180 
181 
182  char * all_symbols = (char*)CTF_int::alloc(MAX_TOT_SYMBOLS_LEN);
183  char * recv_symbols = (char*)CTF_int::alloc(MAX_TOT_SYMBOLS_LEN);
184  FILE * output = NULL;
185 
186  //CTF_int::update_all_models(comm);
187  if (rank == 0){
189 
190  char filename[300];
191  char part[300];
192 
193  sprintf(filename, "profile.%s.",name);
194  srand(time(NULL));
195  sprintf(filename+strlen(filename), "%d.", output_file_counter);
196  output_file_counter++;
197 
198  int off;
199  if (main_argc > 0){
200  for (i=0; i<main_argc; i++){
201  for (off=strlen(main_argv[i]); off>=1; off--){
202  if (main_argv[i][off-1] == '/') break;
203  }
204  sprintf(filename+strlen(filename), "%s.", main_argv[i]+off);
205  }
206  }
207  sprintf(filename+strlen(filename), "-p%d.out", np);
208 
209 
210  output = stdout;// fopen(filename, "w");
211  printf("%s\n",filename);
212  char heading[MAX_NAME_LENGTH+200];
213  for (i=0; i<MAX_NAME_LENGTH; i++){
214  part[i] = ' ';
215  }
216  part[i] = '\0';
217  sprintf(heading,"%s",part);
218  //sprintf(part,"calls total sec exclusive sec\n");
219  sprintf(part," inclusive exclusive\n");
220  strcat(heading,part);
221  fprintf(output, "%s", heading);
222  for (i=0; i<MAX_NAME_LENGTH; i++){
223  part[i] = ' ';
224  }
225  part[i] = '\0';
226  sprintf(heading,"%s",part);
227  sprintf(part, "calls sec %%");
228  strcat(heading,part);
229  sprintf(part, " sec %%\n");
230  strcat(heading,part);
231  fprintf(output, "%s", heading);
232 
233  }
234  len_symbols = 0;
235  for (i=0; i<(int)function_timers->size(); i++){
236  sprintf(all_symbols+len_symbols, "%s", (*function_timers)[i].name);
237  len_symbols += strlen((*function_timers)[i].name)+1;
238  }
239  if (np > 1){
240  for (int lp=1; lp<log2(np)+1; lp++){
241  int gap = 1<<lp;
242  if (rank%gap == gap/2){
243  PMPI_Send(&len_symbols, 1, MPI_INT, rank-gap/2, 1, comm);
244  PMPI_Send(all_symbols, len_symbols, MPI_CHAR, rank-gap/2, 2, comm);
245  }
246  if (rank%gap==0 && rank+gap/2<np){
247  MPI_Status stat;
248  PMPI_Recv(&nrecv_symbols, 1, MPI_INT, rank+gap/2, 1, comm, &stat);
249  PMPI_Recv(recv_symbols, nrecv_symbols, MPI_CHAR, rank+gap/2, 2, comm, &stat);
250  for (i=0; i<nrecv_symbols; i+=strlen(recv_symbols+i)+1){
251  j=0;
252  while (j<len_symbols && strcmp(all_symbols+j, recv_symbols+i) != 0){
253  j+=strlen(all_symbols+j)+1;
254  }
255 
256  if (j>=len_symbols){
257  sprintf(all_symbols+len_symbols, "%s", recv_symbols+i);
258  len_symbols += strlen(recv_symbols+i)+1;
259  }
260  }
261  }
262  }
263  PMPI_Bcast(&len_symbols, 1, MPI_INT, 0, comm);
264  PMPI_Bcast(all_symbols, len_symbols, MPI_CHAR, 0, comm);
265  j=0;
266  while (j<len_symbols){
267  Timer t(all_symbols+j);
268  j+=strlen(all_symbols+j)+1;
269  }
270  }
271  ASSERT(len_symbols <= MAX_TOT_SYMBOLS_LEN);
272 
273  std::sort(function_timers->begin(), function_timers->end(),comp_name);
274  for (i=0; i<(int)function_timers->size(); i++){
275  (*function_timers)[i].compute_totals(comm);
276  }
277  std::sort(function_timers->begin(), function_timers->end());
278  complete_time = (*function_timers)[0].total_time;
279  if (rank == 0){
280  for (i=0; i<(int)function_timers->size(); i++){
281  (*function_timers)[i].print(output,comm,rank,np);
282  }
283  }
284 
285  cdealloc(recv_symbols);
286  cdealloc(all_symbols);
287 
288  /* if (rank == 0){
289  fclose(output);
290  } */
291 
292  }
293 
294  void Timer::exit(){
295  #ifdef PROFILE
296  if (set_contxt && original && !exited) {
297  if (comm != MPI_COMM_WORLD){
298  //function_timers->clear();
299  return;
300  }
301  print_timers("all");
302  function_timers->clear();
303  delete function_timers;
304  function_timers = NULL;
305  }
306  #endif
307  }
308 
309  void set_main_args(int argc, const char * const * argv){
310  main_argv = argv;
311  main_argc = argc;
312  }
313 
314  void set_context(MPI_Comm ctxt){
315  if (!set_contxt)
316  comm = ctxt;
317  set_contxt = 1;
318  }
319 
320  Timer_epoch::Timer_epoch(char const * name_){
321  #ifdef PROFILE
322  name = name_;
323  #endif
324  }
325 
327  #ifdef PROFILE
328  tmr_outer = new Timer(name);
329  tmr_outer->start();
330  saved_function_timers = *function_timers;
331  save_excl_time = excl_time;
332  excl_time = 0.0;
333  function_timers->clear();
334  tmr_inner = new Timer(name);
335  tmr_inner->start();
336  #endif
337  }
338 
340  #ifdef PROFILE
341  tmr_inner->stop();
342  if (function_timers != NULL){
343  function_timers->clear();
344  delete function_timers;
345  }
346  function_timers = new std::vector<Function_timer>();
347  *function_timers = saved_function_timers;
348  excl_time = save_excl_time;
349  tmr_outer->stop();
350  //delete tmr_inner;
351  delete tmr_outer;
352  #endif
353  }
354 }
CTF::Timer Timer
Definition: back_comp.h:14
void set_main_args(int argc, const char *const *argv)
Definition: int_timer.cxx:309
void exit()
Definition: int_timer.cxx:294
Timer_epoch(char const *name_)
Definition: int_timer.cxx:320
int main_argc
Definition: int_timer.cxx:20
double start_excl_time
Definition: timer.h:23
MPI_Comm comm
Definition: int_timer.cxx:22
def rank(self)
Definition: core.pyx:312
const char *const * main_argv
Definition: int_timer.cxx:21
times a specific symbol
Definition: timer.h:19
double start_time
Definition: timer.h:22
Function_timer(char const *name_, double const start_time_, double const start_excl_time_)
Definition: int_timer.cxx:28
void stop()
Definition: int_timer.cxx:151
local process walltime measurement
Definition: timer.h:50
#define ASSERT(...)
Definition: util.h:88
int set_contxt
Definition: int_timer.cxx:25
void * alloc(int64_t len)
alloc abstraction
Definition: memcontrol.cxx:365
char name[MAX_NAME_LENGTH]
Definition: timer.h:21
double acc_time
Definition: timer.h:24
int output_file_counter
Definition: int_timer.cxx:26
Timer(char const *name)
Definition: int_timer.cxx:107
double acc_excl_time
Definition: timer.h:25
void print_all_models()
Definition: model.cxx:23
void print(FILE *output, MPI_Comm const comm, int const rank, int const np)
Definition: int_timer.cxx:74
double total_excl_time
Definition: timer.h:29
void set_context(MPI_Comm ctxt)
Definition: int_timer.cxx:314
#define MAX_NAME_LENGTH
Definition: timer.h:14
double total_time
Definition: timer.h:28
void compute_totals(MPI_Comm comm)
Definition: int_timer.cxx:61
void print_timers(char const *name)
Definition: int_timer.cxx:172
bool operator<(Function_timer const &w) const
Definition: int_timer.cxx:70
void start()
Definition: int_timer.cxx:141
int cdealloc(void *ptr)
free abstraction
Definition: memcontrol.cxx:480
Definition: apsp.cxx:17
bool comp_name(Function_timer const &w1, Function_timer const &w2)
Definition: int_timer.cxx:101
double excl_time
Definition: int_timer.cxx:23
#define MAX_TOT_SYMBOLS_LEN
Definition: int_timer.cxx:18
double complete_time
Definition: int_timer.cxx:24
def np(self)
Definition: core.pyx:315