Code beautification with uncrustify
[alexxy/gromacs.git] / src / gromacs / gmxlib / thread_mpi / profile.c
1 /*
2    This source code file is part of thread_mpi.
3    Written by Sander Pronk, Erik Lindahl, and possibly others.
4
5    Copyright (c) 2009, Sander Pronk, Erik Lindahl.
6    All rights reserved.
7
8    Redistribution and use in source and binary forms, with or without
9    modification, are permitted provided that the following conditions are met:
10    1) Redistributions of source code must retain the above copyright
11    notice, this list of conditions and the following disclaimer.
12    2) Redistributions in binary form must reproduce the above copyright
13    notice, this list of conditions and the following disclaimer in the
14    documentation and/or other materials provided with the distribution.
15    3) Neither the name of the copyright holders nor the
16    names of its contributors may be used to endorse or promote products
17    derived from this software without specific prior written permission.
18
19    THIS SOFTWARE IS PROVIDED BY US ''AS IS'' AND ANY
20    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22    DISCLAIMED. IN NO EVENT SHALL WE BE LIABLE FOR ANY
23    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30    If you want to redistribute modifications, please consider that
31    scientific software is very special. Version control is crucial -
32    bugs must be traceable. We will be happy to consider code for
33    inclusion in the official distribution, but derived work should not
34    be called official thread_mpi. Details are found in the README & COPYING
35    files.
36  */
37
38
39 /* the profiling functions */
40
41 #ifdef HAVE_TMPI_CONFIG_H
42 #include "tmpi_config.h"
43 #endif
44
45 #ifdef HAVE_CONFIG_H
46 #include "config.h"
47 #endif
48
49 #ifdef HAVE_UNISTD_H
50 #include <unistd.h>
51 #endif
52
53 #include <errno.h>
54 #include <stdlib.h>
55 #include <stdio.h>
56 #include <string.h>
57 #if !(defined( _WIN32 ) || defined( _WIN64 ) )
58 #include <sys/time.h>
59 #else
60 /* windows doesn't do standard C */
61 #define snprintf sprintf_s
62 #endif
63
64
65 #include "impl.h"
66
67 #ifdef TMPI_TRACE
68 #include <stdarg.h>
69 #endif
70
71 int tMPI_Profile_started = 0;
72
73
74 /* this must match the tmpi_functions enum: */
75 const char *tmpi_function_names[] =
76 {
77     "Send",
78     "Recv",
79     "Sendrecv",
80     "Isend",
81     "Irecv",
82     "Wait",
83     "Test",
84     "Waitall",
85     "Testall",
86     "Waitany",
87     "Testany",
88     "Waitsome",
89     "Testsome",
90
91     "Barrier",
92
93     "Bcast",
94     "Gather",
95     "Gatherv",
96     "Scatter",
97     "Scatterv",
98     "Alltoall",
99     "Alltoallv",
100     "Reduce",
101     "Allreduce",
102     "Scan"
103 };
104
105
106 /* this must match the tmpi_wait_functions enum: */
107 const char *tmpi_waitfn_names[] =
108 {
109     "P2p",
110     "P2p signal",
111     "Coll. send",
112     "Coll. recv",
113     "Barrier",
114     "(All)Reduce",
115 };
116
117
118
119 /* we intentionally only do the ifdef here; this supresses warnings at the link
120    stage about empty object files */
121 #ifdef TMPI_PROFILE
122
123 void tMPI_Profile_init(struct tmpi_profile *prof)
124 {
125     int i;
126
127     /* reset counters */
128     for (i = 0; i < TMPIFN_Nfunctions; i++)
129     {
130         prof->mpifn_calls[i] = 0;
131     }
132 #ifdef TMPI_CYCLE_COUNT
133     for (i = 0; i < TMPIFN_Nfunctions; i++)
134     {
135         prof->mpifn_cycles[i] = 0;
136     }
137     for (i = 0; i < TMPIWAIT_N; i++)
138     {
139         prof->wait_cycles[i] = 0;
140     }
141     prof->global_start = tmpi_cycles_read();
142     prof->global_stop  = 0;
143     prof->wait_start   = 0;
144 #endif
145
146     prof->buffered_p2p_xfers  = 0;
147     prof->buffered_coll_xfers = 0;
148     prof->total_p2p_xfers     = 0;
149     prof->total_coll_xfers    = 0;
150     tMPI_Profile_started      = 1;
151 }
152
153
154 #if 0
155 void tMPI_Profile_destroy(struct tmpi_profile *prof)
156 {
157 }
158 #endif
159
160
161
162 void tMPI_Profile_stop(struct tmpi_profile *prof)
163 {
164 #ifdef TMPI_CYCLE_COUNT
165     prof->global_stop = tmpi_cycles_read();
166 #endif
167     tMPI_Profile_started = 0;
168 }
169
170 /* output functions */
171 void tMPI_Profiles_summarize(int Nthreads, struct tmpi_thread *threads)
172 {
173     int i, j, len = 0;
174
175     printf("\nTMPI PROFILE:\n");
176     printf("%11s", " ");
177     len += 11;
178     for (j = 0; j < Nthreads; j++)
179     {
180         char thrn[128];
181         snprintf(thrn, sizeof(thrn), "Thread %d", j);
182         printf(" %10s", thrn);
183         len += 11;
184     }
185     printf(" %10s\n", "Total");
186     len += 11;
187
188     /* print line */
189     for (i = 0; i < len; i++)
190     {
191         printf("-");
192     }
193     printf("\n");
194
195     for (i = 0; i < TMPIFN_Nfunctions; i++)
196     {
197         long unsigned int total = 0;
198
199         printf("%11s", tmpi_function_names[i]);
200         for (j = 0; j < Nthreads; j++)
201         {
202             long unsigned int count = threads[j].profile.mpifn_calls[i];
203
204             total += count;
205             printf(" %10ld", (long)count);
206         }
207         printf(" %10ld\n", (long)total);
208     }
209
210     printf("\nFraction of buffered transfers:\n");
211     {
212         long unsigned int tot_buf   = 0;
213         long unsigned int tot_count = 0;
214         printf("%11s", "P2p");
215         for (j = 0; j < Nthreads; j++)
216         {
217             long unsigned int buf   = threads[j].profile.buffered_p2p_xfers;
218             long unsigned int count = threads[j].profile.total_p2p_xfers;
219
220             tot_buf   += buf;
221             tot_count += count;
222
223             printf(" %10.5f", (double)buf/(double)count);
224         }
225         printf(" %10.5f\n", (double)tot_buf/(double)tot_count);
226
227         tot_buf   = 0;
228         tot_count = 0;
229         printf("%11s", "Collective");
230         for (j = 0; j < Nthreads; j++)
231         {
232             long unsigned int buf   = threads[j].profile.buffered_coll_xfers;
233             long unsigned int count = threads[j].profile.total_coll_xfers;
234
235             tot_buf   += buf;
236             tot_count += count;
237
238             printf(" %10.5f", (double)buf/(double)count);
239         }
240         printf(" %10.5f\n", (double)tot_buf/(double)tot_count);
241     }
242
243
244 #ifdef TMPI_CYCLE_COUNT
245     printf("\nCall times as fraction of total run time:\n");
246     for (j = 0; j < Nthreads; j++)
247     {
248         threads[j].profile.totals = 0.;
249     }
250     for (i = 0; i < TMPIFN_Nfunctions; i++)
251     {
252         double tot_time = 0.;
253         double tot_diff = 0.;
254
255         printf("%11s", tmpi_function_names[i]);
256         for (j = 0; j < Nthreads; j++)
257         {
258             double time = (double)(threads[j].profile.global_stop -
259                                    threads[j].profile.global_start );
260             double diff = ((double)threads[j].profile.mpifn_cycles[i]);
261             tot_time                  += time;
262             tot_diff                  += diff;
263             threads[j].profile.totals += diff;
264             printf(" %10.5f", diff/time);
265         }
266         printf(" %10.5f\n", tot_diff/tot_time);
267     }
268     {
269         double tot_time = 0.;
270         double tot_diff = 0.;
271
272         printf("%11s", "Total");
273         for (j = 0; j < Nthreads; j++)
274         {
275             double time = (double)(threads[j].profile.global_stop -
276                                    threads[j].profile.global_start );
277             double diff = threads[j].profile.totals;
278
279             tot_time += time;
280             tot_diff += diff;
281             printf(" %10.5f", diff/time );
282         }
283         printf(" %10.5f\n", tot_diff/tot_time);
284     }
285
286
287     printf("\nWait times as fraction of total run time:\n");
288     for (j = 0; j < Nthreads; j++)
289     {
290         threads[j].profile.totals = 0.;
291     }
292
293     for (i = 0; i < TMPIWAIT_N; i++)
294     {
295         double tot_time = 0.;
296         double tot_diff = 0.;
297
298         printf("%11s", tmpi_waitfn_names[i]);
299         for (j = 0; j < Nthreads; j++)
300         {
301             double time = (double)(threads[j].profile.global_stop -
302                                    threads[j].profile.global_start );
303             double diff = ((double)threads[j].profile.wait_cycles[i]);
304             tot_time                  += time;
305             tot_diff                  += diff;
306             threads[j].profile.totals += diff;
307             printf(" %10.5f", diff/time);
308         }
309         printf(" %10.5f\n", tot_diff/tot_time);
310     }
311
312     {
313         double tot_time = 0.;
314         double tot_diff = 0.;
315
316         printf("%11s", "Total");
317         for (j = 0; j < Nthreads; j++)
318         {
319             double time = (double)(threads[j].profile.global_stop -
320                                    threads[j].profile.global_start );
321             double diff = threads[j].profile.totals;
322
323             tot_time += time;
324             tot_diff += diff;
325             printf(" %10.5f", diff/time );
326         }
327         printf(" %10.5f\n", tot_diff/tot_time);
328     }
329 #endif
330     /* print line */
331     for (i = 0; i < len; i++)
332     {
333         printf("-");
334     }
335     printf("\n");
336
337     /* here we make use of the fact that this is how we calculate tMPI_Wtime */
338     {
339         double wt   = tMPI_Wtime();
340         double wtck = tMPI_Wtick();
341         printf("\nTotal run time: %g +/- %g s.\n", wt, wtck);
342     }
343
344     printf("\n");
345
346 }
347
348 #endif