xref: /petsc/include/petsclog.h (revision ab74092d621b1dcc910f3dccd6d9a6662dba523c)
1 /* $Id: petsclog.h,v 1.155 2001/09/06 14:51:20 bsmith Exp $ */
2 
3 /*
4     Defines profile/logging in PETSc.
5 */
6 
7 #if !defined(__PetscLog_H)
8 #define __PetscLog_H
9 #include "petsc.h"
10 
11 /*
12   Each PETSc object class has it's own cookie (internal integer in the
13   data structure used for error checking). These are all defined by an offset
14   from the lowest one, PETSC_COOKIE.
15 */
16 #define PETSC_COOKIE 1211211
17 extern int PETSC_LARGEST_COOKIE;
18 #define PETSC_EVENT  1311311
19 extern int PETSC_LARGEST_EVENT;
20 
21 /* Events for the Petsc standard library */
22 extern int PETSC_Barrier;
23 
24 /* Global flop counter */
25 extern PetscLogDouble _TotalFlops;
26 
27 /* General logging of information; different from event logging */
28 EXTERN int        PetscLogInfo(void*,const char[],...) PETSC_PRINTF_FORMAT_CHECK(2,3);
29 EXTERN int        PetscLogInfoDeactivateClass(int);
30 EXTERN int        PetscLogInfoActivateClass(int);
31 extern PetscTruth PetscLogPrintInfo;  /* if true, indicates PetscLogInfo() is turned on */
32 
33 #if defined(PETSC_USE_LOG)  /* --- Logging is turned on --------------------------------*/
34 
35 /*
36    Flop counting:  We count each arithmetic operation (e.g., addition, multiplication) separately.
37 
38    For the complex numbers version, note that
39        1 complex addition = 2 flops
40        1 complex multiplication = 6 flops,
41    where we define 1 flop as that for a double precision scalar.  We roughly approximate
42    flop counting for complex numbers by multiplying the total flops by 4; this corresponds
43    to the assumption that we're counting mostly additions and multiplications -- and
44    roughly the same number of each.  More accurate counting could be done by distinguishing
45    among the various arithmetic operations.
46  */
47 
48 #if defined(PETSC_USE_COMPLEX)
49 #define PetscLogFlops(n) (_TotalFlops += (4*n),0)
50 #else
51 #define PetscLogFlops(n) (_TotalFlops += (n),0)
52 #endif
53 
54 #if defined (PETSC_HAVE_MPE)
55 #include "mpe.h"
56 EXTERN int        PetscLogMPEBegin(void);
57 EXTERN int        PetscLogMPEDump(const char[]);
58 extern PetscTruth UseMPE;
59 #define PETSC_LOG_EVENT_MPE_BEGIN(e) \
60   if(UseMPE && _stageLog->eventLog[_stageLog->curStage]->eventInfo[e].active) \
61     MPE_Log_event(_stageLog->eventLog[_stageLog->curStage]->eventInfo[e].mpe_id_begin,0,"");
62 
63 #define PETSC_LOG_EVENT_MPE_END(e) \
64   if(UseMPE && _stageLog->eventLog[_stageLog->curStage]->eventInfo[e].active) \
65     MPE_Log_event(_stageLog->eventLog[_stageLog->curStage]->eventInfo[e].mpe_id_end,0,"");
66 
67 #else
68 #define PETSC_LOG_EVENT_MPE_BEGIN(e)
69 #define PETSC_LOG_EVENT_MPE_END(e)
70 #endif
71 
72 EXTERN int (*_PetscLogPLB)(int,int,PetscObject,PetscObject,PetscObject,PetscObject);
73 EXTERN int (*_PetscLogPLE)(int,int,PetscObject,PetscObject,PetscObject,PetscObject);
74 EXTERN int (*_PetscLogPHC)(PetscObject);
75 EXTERN int (*_PetscLogPHD)(PetscObject);
76 
77 #define PetscLogObjectParent(p,c) \
78   if (c) {\
79     PetscValidHeader((PetscObject)(c));\
80     PetscValidHeader((PetscObject)(p));\
81     ((PetscObject)(c))->parent = (PetscObject)(p);\
82     ((PetscObject)(c))->parentid = ((PetscObject)p)->id;\
83   }
84 #define PetscLogObjectParents(p,n,d) {int _i; for (_i=0; _i<n; _i++) PetscLogObjectParent(p,(d)[_i]);}
85 #define PetscLogObjectCreate(h)      {if (_PetscLogPHC) (*_PetscLogPHC)((PetscObject)h);}
86 #define PetscLogObjectDestroy(h)     {if (_PetscLogPHD) (*_PetscLogPHD)((PetscObject)h);}
87 #define PetscLogObjectMemory(p,m)    {PetscValidHeader((PetscObject)p);((PetscObject)(p))->mem += (m);}
88 /* Initialization functions */
89 EXTERN int PetscLogBegin(void);
90 EXTERN int PetscLogAllBegin(void);
91 EXTERN int PetscLogTraceBegin(FILE *);
92 /* General functions */
93 EXTERN int PetscLogGetRGBColor(char **);
94 EXTERN int PetscLogDestroy(void);
95 EXTERN int PetscLogSet(int (*)(int, int, PetscObject, PetscObject, PetscObject, PetscObject),
96                    int (*)(int, int, PetscObject, PetscObject, PetscObject, PetscObject));
97 EXTERN int PetscLogObjectState(PetscObject, const char[], ...)  PETSC_PRINTF_FORMAT_CHECK(2,3);
98 /* Output functions */
99 EXTERN int PetscLogPrintSummary(MPI_Comm, const char[]);
100 EXTERN int PetscLogDump(const char[]);
101 /* Counter functions */
102 EXTERN int PetscGetFlops(PetscLogDouble *);
103 /* Stage functions */
104 EXTERN int PetscLogStageRegister(int *, const char[]);
105 EXTERN int PetscLogStagePush(int);
106 EXTERN int PetscLogStagePop(void);
107 EXTERN int PetscLogStageSetVisible(int, PetscTruth);
108 EXTERN int PetscLogStageGetVisible(int, PetscTruth *);
109 EXTERN int PetscLogStageGetId(const char [], int *);
110 /* Event functions */
111 EXTERN int PetscLogEventRegister(int *, const char[], int);
112 EXTERN int PetscLogEventActivate(int);
113 EXTERN int PetscLogEventDeactivate(int);
114 EXTERN int PetscLogEventActivateClass(int);
115 EXTERN int PetscLogEventDeactivateClass(int);
116 /* Class functions */
117 EXTERN int PetscLogClassRegister(int *, const char []);
118 
119 /* Default log */
120 typedef struct _StageLog *StageLog;
121 extern StageLog _stageLog;
122 
123 /* Global counters */
124 extern PetscLogDouble irecv_ct,  isend_ct,  recv_ct,  send_ct;
125 extern PetscLogDouble irecv_len, isend_len, recv_len, send_len;
126 extern PetscLogDouble allreduce_ct;
127 extern PetscLogDouble wait_ct, wait_any_ct, wait_all_ct, sum_of_waits_ct;
128 extern int            PETSC_DUMMY, PETSC_DUMMY_SIZE;
129 
130 /* We must make these structures available if we are to access the event
131    activation flags in the PetscLogEventBegin/End() macros. If we forced a
132    function call each time, we could leave these structures in plog.h
133 */
134 /* The structure for logging performance */
135 typedef struct _PerfInfo {
136   char          *name;          /* The name of this section */
137   int            id;            /* The integer identifying this event */
138   int            cookie;        /* The class id for this section */
139   PetscTruth     active;        /* The flag to activate logging */
140   PetscTruth     visible;       /* The flag to print info in summary */
141   int            depth;         /* The nesting depth of the event call */
142   int            count;         /* The number of times this section was executed */
143   PetscLogDouble flops;         /* The flops used in this section */
144   PetscLogDouble time;          /* The time taken for this section */
145   PetscLogDouble numMessages;   /* The number of messages in this section */
146   PetscLogDouble messageLength; /* The total message lengths in this section */
147   PetscLogDouble numReductions; /* The number of reductions in this section */
148 #if defined (PETSC_HAVE_MPE)
149   int           mpe_id_begin;   /* MPE ids that define the event */
150   int           mpe_id_end;
151 #endif
152 } PerfInfo;
153 
154 /* The structure for logging events */
155 typedef struct _EventLog *EventLog;
156 struct _EventLog {
157   int       numEvents;   /* The number of registered events */
158   int       maxEvents;   /* The maximum number of events */
159   PerfInfo *eventInfo;   /* The performance information for each event */
160 };
161 typedef int PetscEvent;
162 
163 /* The structure for logging class information */
164 typedef struct _ClassInfo {
165   char          *name;          /* The class name */
166   int            cookie;        /* The integer identifying this class */
167   int            creations;     /* The number of objects of this class created */
168   int            destructions;  /* The number of objects of this class destroyed */
169   PetscLogDouble mem;           /* The total memory allocated by objects of this class */
170   PetscLogDouble descMem;       /* The total memory allocated by descendents of these objects */
171 } ClassInfo;
172 
173 typedef struct _ClassLog *ClassLog;
174 struct _ClassLog {
175   int        numClasses; /* The number of classes registered */
176   int        maxClasses; /* The maximum number of classes */
177   ClassInfo *classInfo;  /* The structure for classs information (cookies are monotonicly increasing) */
178 };
179 
180 /* A simple stack (should replace) */
181 typedef struct _IntStack *IntStack;
182 
183 /* The structure for logging in stages */
184 struct _StageLog {
185   /* Size information */
186   int         numStages;    /* The number of registered stages */
187   int         maxStages;    /* The maximum number of stages */
188   /* Runtime information */
189   IntStack    stack;        /* The stack for active stages */
190   int         curStage;     /* The current stage (only used in macros so we don't call StackTop) */
191   /* Stage specific information */
192   PerfInfo   *stageInfo;    /* The performance information for each stage */
193   EventLog   *eventLog;     /* The event log for each stage */
194   ClassLog   *classLog;     /* The class information for each stage */
195 };
196 
197 #define PetscLogEventBarrierBegin(e,o1,o2,o3,o4,cm) 0; \
198 {\
199   int _2_ierr;\
200   if (_PetscLogPLB && _stageLog->eventLog[_stageLog->curStage]->eventInfo[e].active) {\
201     _2_ierr = PetscLogEventBegin((e),o1,o2,o3,o4);CHKERRQ(_2_ierr);\
202     _2_ierr = MPI_Barrier(cm);CHKERRQ(_2_ierr);\
203     _2_ierr = PetscLogEventEnd((e),o1,o2,o3,o4);CHKERRQ(_2_ierr);\
204   }\
205   _2_ierr = PetscLogEventBegin((e)+1,o1,o2,o3,o4);CHKERRQ(_2_ierr);\
206 }
207 
208 #define PetscLogEventBegin(e,o1,o2,o3,o4) 0; \
209 {\
210   if (_PetscLogPLB && _stageLog->eventLog[_stageLog->curStage]->eventInfo[e].active) {\
211     (*_PetscLogPLB)((e),0,(PetscObject)(o1),(PetscObject)(o2),(PetscObject)(o3),(PetscObject)(o4));\
212   }\
213   PETSC_LOG_EVENT_MPE_BEGIN(e); \
214 }
215 
216 #define PetscLogEventBarrierEnd(e,o1,o2,o3,o4,cm) PetscLogEventEnd(e+1,o1,o2,o3,o4)
217 
218 #define PetscLogEventEnd(e,o1,o2,o3,o4) 0; \
219 {\
220   if (_PetscLogPLE && _stageLog->eventLog[_stageLog->curStage]->eventInfo[e].active) {\
221     (*_PetscLogPLE)((e),0,(PetscObject)(o1),(PetscObject)(o2),(PetscObject)(o3),(PetscObject)(o4));\
222   }\
223   PETSC_LOG_EVENT_MPE_END(e); \
224 }
225 
226 /*
227      This does not work for MPI-Uni because our src/mpiuni/mpi.h file
228    uses macros to defined the MPI operations.
229 
230      It does not work correctly from HP-UX because it processes the
231    macros in a way that sometimes it double counts, hence
232    PETSC_HAVE_BROKEN_RECURSIVE_MACRO
233 
234      It does not work with Windows NT because winmpich lacks MPI_Type_size()
235 */
236 #if !defined(PETSC_HAVE_MPI_UNI) && !defined(PETSC_HAVE_BROKEN_RECURSIVE_MACRO) && !defined (PETSC_HAVE_MPI_MISSING_TYPESIZE)
237 /*
238    Logging of MPI activities
239 */
240 
241 #define TypeSize(buff,count,type) \
242 (\
243   MPI_Type_size(type,&PETSC_DUMMY_SIZE),buff += ((PetscLogDouble) ((count)*PETSC_DUMMY_SIZE))\
244 )
245 
246 #define MPI_Irecv(buf,count, datatype,source,tag,comm,request) \
247 (\
248   PETSC_DUMMY = MPI_Irecv(buf,count, datatype,source,tag,comm,request),\
249   irecv_ct++,TypeSize(irecv_len,count,datatype),PETSC_DUMMY\
250 )
251 
252 #define MPI_Isend(buf,count, datatype,dest,tag,comm,request) \
253 (\
254   PETSC_DUMMY = MPI_Isend(buf,count, datatype,dest,tag,comm,request),\
255   isend_ct++,  TypeSize(isend_len,count,datatype),PETSC_DUMMY\
256 )
257 
258 #define MPI_Startall_irecv(count,number,requests) \
259 (\
260   PETSC_DUMMY = MPI_Startall(number,requests),\
261   irecv_ct += (PetscLogDouble)(number),irecv_len += ((PetscLogDouble) ((count)*sizeof(PetscScalar))),PETSC_DUMMY\
262 )
263 
264 #define MPI_Startall_isend(count,number,requests) \
265 (\
266   PETSC_DUMMY = MPI_Startall(number,requests),\
267   isend_ct += (PetscLogDouble)(number),isend_len += ((PetscLogDouble) ((count)*sizeof(PetscScalar))),PETSC_DUMMY\
268 )
269 
270 #define MPI_Start_isend(count, requests) \
271 (\
272   PETSC_DUMMY = MPI_Start(requests),\
273   isend_ct++,isend_len += ((PetscLogDouble) ((count)*sizeof(PetscScalar))),PETSC_DUMMY\
274 )
275 
276 #define MPI_Recv(buf,count, datatype,source,tag,comm,status) \
277 (\
278   PETSC_DUMMY = MPI_Recv(buf,count, datatype,source,tag,comm,status),\
279   recv_ct++,TypeSize(recv_len,count,datatype),PETSC_DUMMY\
280 )
281 
282 #define MPI_Send(buf,count, datatype,dest,tag,comm) \
283 (\
284   PETSC_DUMMY = MPI_Send(buf,count, datatype,dest,tag,comm),\
285   send_ct++, TypeSize(send_len,count,datatype),PETSC_DUMMY\
286 )
287 
288 #define MPI_Wait(request,status) \
289 (\
290   wait_ct++,sum_of_waits_ct++,\
291   MPI_Wait(request,status)\
292 )
293 
294 #define MPI_Waitany(a,b,c,d) \
295 (\
296   wait_any_ct++,sum_of_waits_ct++,\
297   MPI_Waitany(a,b,c,d)\
298 )
299 
300 #define MPI_Waitall(count,array_of_requests,array_of_statuses) \
301 (\
302   wait_all_ct++,sum_of_waits_ct += (PetscLogDouble) (count),\
303   MPI_Waitall(count,array_of_requests,array_of_statuses)\
304 )
305 
306 #define MPI_Allreduce(sendbuf, recvbuf,count,datatype,op,comm) \
307 (\
308   allreduce_ct++,MPI_Allreduce(sendbuf,recvbuf,count,datatype,op,comm)\
309 )
310 
311 #else
312 
313 #define MPI_Startall_irecv(count,number,requests) \
314 (\
315   MPI_Startall(number,requests)\
316 )
317 
318 #define MPI_Startall_isend(count,number,requests) \
319 (\
320   MPI_Startall(number,requests)\
321 )
322 
323 #define MPI_Start_isend(count, requests) \
324 (\
325   MPI_Start(requests)\
326 )
327 
328 #endif /* !PETSC_HAVE_MPI_UNI && ! PETSC_HAVE_BROKEN_RECURSIVE_MACRO */
329 
330 #else  /* ---Logging is turned off --------------------------------------------*/
331 
332 #define PetscLogFlops(n) 0
333 
334 /*
335      With logging turned off, then MPE has to be turned off
336 */
337 #define PetscLogMPEBegin()         0
338 #define PetscLogMPEDump(a)         0
339 
340 #define PetscLogEventActivate(a)   0
341 #define PetscLogEventDeactivate(a) 0
342 
343 #define PetscLogEventActivateClass(a)   0
344 #define PetscLogEventDeactivateClass(a) 0
345 
346 #define _PetscLogPLB                        0
347 #define _PetscLogPLE                        0
348 #define _PetscLogPHC                        0
349 #define _PetscLogPHD                        0
350 #define PetscGetFlops(a)                (*(a) = 0.0,0)
351 #define PetscLogEventBegin(e,o1,o2,o3,o4)   0
352 #define PetscLogEventEnd(e,o1,o2,o3,o4)     0
353 #define PetscLogEventBarrierBegin(e,o1,o2,o3,o4,cm) 0
354 #define PetscLogEventBarrierEnd(e,o1,o2,o3,o4,cm)   0
355 #define PetscLogObjectParent(p,c)
356 #define PetscLogObjectParents(p,n,c)
357 #define PetscLogObjectCreate(h)
358 #define PetscLogObjectDestroy(h)
359 #define PetscLogObjectMemory(p,m)
360 #define PetscLogDestroy()                   0
361 #define PetscLogStagePush(a)                0
362 #define PetscLogStagePop()                  0
363 #define PetscLogStageRegister(a,b)          0
364 #define PetscLogStagePrint(a,flg)           0
365 #define PetscLogPrintSummary(comm,file)     0
366 #define PetscLogBegin()                     0
367 #define PetscLogTraceBegin(file)            0
368 #define PetscLogSet(lb,le)                  0
369 #define PetscLogAllBegin()                  0
370 #define PetscLogDump(c)                     0
371 #define PetscLogEventRegister(a,b,c)        0
372 EXTERN int PetscLogObjectState(PetscObject,const char[],...) PETSC_PRINTF_FORMAT_CHECK(2,3);
373 
374 /* If PETSC_USE_LOG is NOT defined, these still need to be! */
375 #define MPI_Startall_irecv(count,number,requests) MPI_Startall(number,requests)
376 #define MPI_Startall_isend(count,number,requests) MPI_Startall(number,requests)
377 #define MPI_Start_isend(count,requests) MPI_Start(requests)
378 
379 #endif   /* PETSC_USE_LOG */
380 
381 extern PetscTruth PetscPreLoadingUsed;       /* true if we are or have done preloading */
382 extern PetscTruth PetscPreLoadingOn;         /* true if we are currently in a preloading calculation */
383 
384 #define PreLoadBegin(flag,name) \
385 {\
386   PetscTruth PreLoading = flag;\
387   int        PreLoadMax,PreLoadIt,_stageNum,_3_ierr;\
388   _3_ierr = PetscOptionsGetLogical(PETSC_NULL,"-preload",&PreLoading,PETSC_NULL);CHKERRQ(_3_ierr);\
389   PreLoadMax = (int)(PreLoading);\
390   PetscPreLoadingUsed = PreLoading ? PETSC_TRUE : PetscPreLoadingUsed;\
391   for (PreLoadIt=0; PreLoadIt<=PreLoadMax; PreLoadIt++) {\
392     PetscPreLoadingOn = PreLoading;\
393     _3_ierr = PetscBarrier(PETSC_NULL);CHKERRQ(_3_ierr);\
394     if (PreLoadIt>0) {\
395       _3_ierr = PetscLogStageGetId(name,&_stageNum);CHKERRQ(_3_ierr);\
396     } else {\
397       _3_ierr = PetscLogStageRegister(&_stageNum,name);CHKERRQ(_3_ierr);\
398       _3_ierr = PetscLogStageSetVisible(_stageNum,(PetscTruth)(!PreLoadMax || PreLoadIt));\
399     }\
400     _3_ierr = PetscLogStagePush(_stageNum);CHKERRQ(_3_ierr);
401 
402 #define PreLoadEnd() \
403     _3_ierr = PetscLogStagePop();CHKERRQ(_3_ierr);\
404     PreLoading = PETSC_FALSE;\
405   }\
406 }
407 
408 #define PreLoadStage(name) \
409   _3_ierr = PetscLogStagePop();CHKERRQ(_3_ierr);\
410   if (PreLoadIt>0) {\
411     _3_ierr = PetscLogStageGetId(name,&_stageNum);CHKERRQ(_3_ierr);\
412   } else {\
413     _3_ierr = PetscLogStageRegister(&_stageNum,name);CHKERRQ(_3_ierr);\
414     _3_ierr = PetscLogStageSetVisible(_stageNum,(PetscTruth)(!PreLoadMax || PreLoadIt));\
415   }\
416   _3_ierr = PetscLogStagePush(_stageNum);CHKERRQ(_3_ierr);
417 #endif
418