handle nested events
[charm.git] / src / ck-perf / trace-utilization.h
1 /*****************************************************************************
2  * $Source$
3  * $Author$
4  * $Date$
5  * $Revision$
6  *****************************************************************************/
7
8 /**
9  * \addtogroup CkPerf
10  */
11 /*@{*/
12
13
14 #ifndef _TRACE_UTILIZATION_H
15 #define _TRACE_UTILIZATION_H
16
17 #include <stdio.h>
18 #include <errno.h>
19 #include <deque>
20
21 #include "charm++.h"
22
23
24 #include "trace.h"
25 #include "envelope.h"
26 #include "register.h"
27 #include "trace-common.h"
28 #include "ckcallback-ccs.h"
29
30 #include "TraceUtilization.decl.h"
31
32 #define INVALIDEP     -2
33 #define TRACEON_EP    -3
34 #define NUM_DUMMY_EPS 9
35
36
37 // initial bin size, time in seconds
38 #define  BIN_PER_SEC    1000
39 #define  BIN_SIZE       0.001
40 #define NUM_BINS      32768
41
42
43 /** Define the types used in the gathering of sum detail statistics for use with CCS */
44 #define numBins_T int
45 #define numProcs_T int
46 #define entriesInBin_T short
47 #define ep_T short
48 #define utilization_T unsigned char
49 #define other_EP 10000
50
51
52 /* readonly */ extern CProxy_TraceUtilizationBOC traceUtilizationGroupProxy;
53
54 void collectUtilizationData(void *data, double currT);
55
56
57
58 /** A main chare that can create the BOC/group */
59 class TraceUtilizationInit : public Chare {
60  public:
61   TraceUtilizationInit(CkArgMsg *m) {
62     CkPrintf("[%d] TraceUtilizationInit creating traceUtilizationGroupProxy");
63     fflush(stdout);
64    
65     traceUtilizationGroupProxy = CProxy_TraceUtilizationBOC::ckNew();
66     
67     CkPrintf("Trace Summary now listening in for CCS Client\n");
68     CcsRegisterHandler("CkPerfSumDetail compressed", CkCallback(CkIndex_TraceUtilizationBOC::ccsRequestSumDetailCompressed(NULL), traceUtilizationGroupProxy[0])); 
69     
70     CkPrintf("[%d] Setting up periodic startCollectData callback\n", CkMyPe());
71     CcdCallOnConditionKeep(CcdPERIODIC_1second, collectUtilizationData, (void *)NULL);
72
73   }
74 };
75
76
77
78
79
80
81 /** 
82     A class that reads/writes a buffer out of different types of data.
83
84     This class exists because I need to get references to parts of the buffer 
85     that have already been used so that I can increment counters inside the buffer.
86 */
87
88 class compressedBuffer {
89  public:
90   char* buf;
91   int pos; ///<< byte position just beyond the previously read/written data
92
93   compressedBuffer(){
94     buf = NULL;
95     pos = 0;
96   }
97
98   compressedBuffer(int bytes){
99     buf = (char*)malloc(bytes);
100     pos = 0;
101   }
102
103   compressedBuffer(void *buffer){
104     buf = (char*)buffer;
105     pos = 0;
106   }
107   
108   void init(void *buffer){
109     buf = (char*)buffer;
110     pos = 0;
111   }
112   
113   inline void * currentPtr(){
114     return (void*)(buf+pos);
115   }
116   
117   template <typename T>
118     T read(int offset){
119     // to resolve unaligned writes causing bus errors, need memcpy
120     T v;
121     memcpy(&v, buf+offset, sizeof(T));
122     return v;
123   }
124   
125   template <typename T>
126     void write(T v, int offset){
127     T v2 = v; // on stack
128     // to resolve unaligned writes causing bus errors, need memcpy
129     memcpy(buf+offset, &v2, sizeof(T));
130   }
131     
132   template <typename T>
133     void increment(int offset){
134     T temp;
135     temp = read<T>(offset);
136     temp ++;
137     write<T>(temp, offset);
138   }
139
140   template <typename T>
141     void accumulate(T v, int offset){
142     T temp;
143     temp = read<T>(offset);
144     temp += v;
145     write<T>(temp, offset);
146   }
147   
148   template <typename T>
149     int push(T v){
150     int oldpos = pos;
151     write<T>(v, pos);
152     pos += sizeof(T);
153     return oldpos;
154   }
155   
156   template <typename T>
157     T pop(){
158     T temp = read<T>(pos);
159     pos += sizeof(T);
160     return temp;
161   }
162
163   template <typename T>
164     T peek(){
165     T temp = read<T>(pos);
166     return temp;
167   }
168
169   template <typename T0, typename T>
170     T peekSecond(){
171     T temp;
172     memcpy(&temp, buf+pos+sizeof(T0), sizeof(T));
173     return temp;
174   }
175
176   int datalength(){
177     return pos;
178   }
179      
180   void * buffer(){
181     return (void*) buf;
182   }  
183
184   void freeBuf(){
185     free(buf);
186   }
187
188   ~compressedBuffer(){
189     // don't free the buf because the user my have supplied the buffer
190   }
191     
192 };
193
194
195
196 compressedBuffer compressAvailableNewSumDetail(int max=10000);
197 void mergeCompressedBin(compressedBuffer *srcBufferArray, int numSrcBuf, int *numProcsRepresentedInMessage, int totalProcsAcrossAllMessages, compressedBuffer &destBuffer);
198 //void printSumDetailInfo(int desiredBinsToSend);
199 CkReductionMsg *sumDetailCompressedReduction(int nMsg,CkReductionMsg **msgs);
200 void printCompressedBuf(compressedBuffer b);
201 compressedBuffer fakeCompressedMessage();
202 compressedBuffer emptyCompressedBuffer();
203 void sanityCheckCompressedBuf(compressedBuffer b);
204 bool isCompressedBufferSane(compressedBuffer b);
205 double averageUtilizationInBuffer(compressedBuffer b);
206
207
208
209
210
211 class TraceUtilization : public Trace {
212  public:
213   int execEp; // the currently executing EP
214   double start; // the start time for the currently executing EP
215
216   unsigned int epInfoSize;
217
218   double *cpuTime;     // NUM_BINS*epInfoSize
219   int lastBinUsed;
220   unsigned int numBinsSent;
221   unsigned int previouslySentBins;
222
223
224   TraceUtilization() {
225     execEp == TRACEON_EP;
226     cpuTime = NULL;
227     lastBinUsed = -1;
228     numBinsSent = 0;
229   }
230
231
232   /// Initialize memory after the number of EPs has been determined
233   void initMem(){
234     int _numEntries=_entryTable.size();
235     epInfoSize = _numEntries + NUM_DUMMY_EPS + 1; // keep a spare EP
236     //    CkPrintf("allocating cpuTime[%d]\n", (int) (NUM_BINS*epInfoSize));
237     cpuTime = new double[NUM_BINS*epInfoSize];
238     _MEMCHECK(cpuTime);
239
240     if(CkMyPe() == 0)
241       writeSts();
242
243   }
244
245   void writeSts(void);
246
247   void creation(envelope *e, int epIdx, int num=1) {}
248
249   void beginExecute(envelope *e);
250   void beginExecute(CmiObjId  *tid);
251   void beginExecute(int event,int msgType,int ep,int srcPe, int mlen=0, CmiObjId *idx=NULL);
252   void endExecute(void);
253   void beginIdle(double currT) {}
254   void endIdle(double currT) {}
255   void beginPack(void){}
256   void endPack(void) {}
257   void beginUnpack(void) {}
258   void endUnpack(void) {}
259   void beginComputation(void) {  initMem(); }
260   void endComputation(void) {}
261   void traceClearEps() {}
262   void traceWriteSts() {}
263   void traceClose() {}
264
265   void addEventType(int eventType);
266   
267   int cpuTimeEntriesAvailable() const { return lastBinUsed+1; }
268   int cpuTimeEntriesSentSoFar() const { return numBinsSent; }
269   void incrementNumCpuTimeEntriesSent(int n) { numBinsSent += n; }
270
271
272   double sumUtilization(int startBin, int endBin);
273
274
275   void updateCpuTime(int epIdx, double startTime, double endTime){
276     
277     //    CkPrintf("updateCpuTime(startTime=%lf endTime=%lf)\n", startTime, endTime);
278     
279     if (epIdx >= epInfoSize) {
280       CkPrintf("WARNING: epIdx=%d >=  epInfoSize=%d\n", (int)epIdx, (int)epInfoSize );
281       return;
282     }
283     
284     int startingBinIdx = (int)(startTime/BIN_SIZE);
285     int endingBinIdx = (int)(endTime/BIN_SIZE);
286     
287     if (startingBinIdx == endingBinIdx) {
288       addToCPUtime(startingBinIdx, epIdx, endTime - startTime);
289     } else if (startingBinIdx < endingBinIdx) { // EP spans intervals
290       addToCPUtime(startingBinIdx, epIdx, (startingBinIdx+1)*BIN_SIZE - startTime);
291       while(++startingBinIdx < endingBinIdx)
292         addToCPUtime(startingBinIdx, epIdx, BIN_SIZE);
293       addToCPUtime(endingBinIdx, epIdx, endTime - endingBinIdx*BIN_SIZE);
294     } 
295   }
296
297
298   /// Zero out all entries from (lastBinUsed+1) up to and including interval.
299   inline void zeroIfNecessary(unsigned int interval){
300     for(unsigned int i=lastBinUsed+1; i<= interval; i++){
301       // zero all eps for this bin
302       for(unsigned int j=0;j<epInfoSize;j++){
303         cpuTime[(i%NUM_BINS)*epInfoSize+j] = 0.0;
304       }
305     }
306     lastBinUsed = interval;
307   }
308     
309   UInt getEpInfoSize() { return epInfoSize; }
310
311   /// for Summary-Detail
312   inline double getCPUtime(unsigned int interval, unsigned int ep) {
313     CkAssert(ep < epInfoSize);
314     if(cpuTime != NULL && interval <= lastBinUsed)
315       return cpuTime[(interval%NUM_BINS)*epInfoSize+ep]; 
316     else {
317       CkPrintf("getCPUtime called with invalid options: cpuTime=%p interval=%d ep=%d\n", cpuTime, (int)interval, (int)ep);
318       return 0.0;
319     }
320   }
321
322   inline void addToCPUtime(unsigned int interval, unsigned int ep, double val){
323     //    CkAssert(ep < epInfoSize);
324     zeroIfNecessary(interval);
325     //    CkPrintf("addToCPUtime interval=%d\n", (int)interval);
326     cpuTime[(interval%NUM_BINS)*epInfoSize+ep] += val;
327   }
328    
329
330   inline double getUtilization(int interval, int ep){
331     return getCPUtime(interval, ep) * 100.0 * (double)BIN_PER_SEC; 
332   }
333
334
335   compressedBuffer compressNRecentSumDetail(int desiredBinsToSend);
336
337
338 };
339
340
341
342
343
344
345 class TraceUtilizationBOC : public CBase_TraceUtilizationBOC {
346   
347   std::deque<CkReductionMsg *> storedSumDetailResults;
348   
349  public:
350   TraceUtilizationBOC() {}
351   TraceUtilizationBOC(CkMigrateMessage* msg) {}
352   ~TraceUtilizationBOC() {}
353  
354
355   /// Entry methods:
356   void ccsRequestSumDetailCompressed(CkCcsRequestMsg *m);
357   void collectSumDetailData();
358   void sumDetailDataCollected(CkReductionMsg *);
359
360 };
361
362
363
364
365
366 #endif
367
368 /*@}*/