Critical path header changes for the pics merge
[charm.git] / src / ck-core / envelope-path.h
1 /**
2 \file
3 \addtogroup CkEnvelope
4 */
5 #ifndef _ENVELOPE_PATH_H
6 #define _ENVELOPE_PATH_H
7
8 #include "pup.h"
9 #include "charm.h"
10
11 // #define USE_CRITICAL_PATH_HEADER_ARRAY
12
13 #if USE_CRITICAL_PATH_HEADER_ARRAY
14 // This critical path detection is still experimental
15 // Added by Isaac (Dec 2008)
16
17 // stores the pointer to the currently executing msg
18 // used in cklocation.C, ck.C
19 // TODO: convert to CkPv
20
21 extern envelope * currentlyExecutingMsg;
22 extern bool thisMethodSentAMessage;
23 extern double timeEntryMethodStarted;
24
25 // The methods provided by the control point framework to access 
26 // the most Critical path seen by this PE. 
27 // These ought not to be called by the user program.
28 // (defined in controlPoints.C)
29 extern void resetPECriticalPath();
30 extern void printPECriticalPath();
31 extern void registerTerminalEntryMethod();
32
33 // Reset the counts for the currently executing message, 
34 // and also reset the PE's critical path detection
35 // To be called by the user program
36 extern void resetCricitalPathDetection();
37
38 // Reset the counts for the currently executing message
39 extern void resetThisEntryPath();
40
41
42
43 #endif
44
45
46 /** static sizes for arrays in PathHistory objects */
47 #define numEpIdxs 150
48 #define numArrayIds 20
49
50 /** A class that is used to track the entry points and other information 
51     about a critical path as a charm++ program executes.
52
53     This class won't do useful things unless USE_CRITICAL_PATH_HEADER_ARRAY is defined
54
55 */
56 class PathHistory {
57  private:
58   int epIdxCount[numEpIdxs];
59   int arrayIdxCount[numArrayIds];
60   double totalTime;
61
62  public:
63   
64   const int* getEpIdxCount(){
65     return epIdxCount;
66   }
67   
68   const int* getArrayIdxCount(){
69     return arrayIdxCount;
70   }
71
72   int getEpIdxCount(int i) const {
73     return epIdxCount[i];
74   }
75   
76   int getArrayIdxCount(int i) const {
77     return arrayIdxCount[i];
78   }
79
80
81   double getTotalTime() const{
82     return totalTime;
83   }
84
85   
86   PathHistory(){
87     reset();
88   }
89
90   void pup(PUP::er &p) {
91     for(int i=0;i<numEpIdxs;i++)
92       p|epIdxCount[i];
93     for(int i=0;i<numArrayIds;i++)
94       p|arrayIdxCount[i];
95     p | totalTime;
96   } 
97   
98   double getTime(){
99     return totalTime;
100   }
101   
102   void reset(){
103     // CkPrintf("reset() currentlyExecutingMsg=%p\n", currentlyExecutingMsg);
104     
105     totalTime = 0.0;
106     
107     for(int i=0;i<numEpIdxs;i++){
108       epIdxCount[i] = 0;
109     }
110     for(int i=0;i<numArrayIds;i++){
111       arrayIdxCount[i]=0;
112     }
113   }
114   
115   int updateMax(const PathHistory & other){
116     if(other.totalTime > totalTime){
117       //          CkPrintf("[%d] Found a longer terminal path:\n", CkMyPe());
118       //          other.print();
119       
120       totalTime = other.totalTime;
121       for(int i=0;i<numEpIdxs;i++){
122         epIdxCount[i] = other.epIdxCount[i];
123       }
124       for(int i=0;i<numArrayIds;i++){
125         arrayIdxCount[i]=other.arrayIdxCount[i];
126       }
127       return 1;
128     }
129     return 0;
130   }
131   
132   
133   void print() const {
134     CkPrintf("Critical Path Time=%lf : ", (double)totalTime);
135     for(int i=0;i<numEpIdxs;i++){
136       if(epIdxCount[i]>0){
137         CkPrintf("EP %d count=%d : ", i, (int)epIdxCount[i]);
138       }
139     }
140     for(int i=0;i<numArrayIds;i++){
141       if(arrayIdxCount[i]>0){
142         CkPrintf("Array %d count=%d : ", i, (int)arrayIdxCount[i]);
143       }
144     }
145     CkPrintf("\n");
146   }
147
148   /// Write a description of the path into the beginning of the provided buffer. The buffer ought to be large enough.
149   void printHTMLToString(char* buf) const {
150     buf[0] = '\0';
151
152     sprintf(buf+strlen(buf), "Path Time=%lf<br>", (double)totalTime);
153     for(int i=0;i<numEpIdxs;i++){
154       if(epIdxCount[i]>0){
155         sprintf(buf+strlen(buf),"EP %d count=%d<br>", i, (int)epIdxCount[i]);
156       }
157     }
158     for(int i=0;i<numArrayIds;i++){
159       if(arrayIdxCount[i]>0){
160         sprintf(buf+strlen(buf), "Array %d count=%d<br>", i, (int)arrayIdxCount[i]);
161       }
162     }
163   }
164   
165   void incrementTotalTime(double time){
166     totalTime += time;
167   }
168   
169
170 #if USE_CRITICAL_PATH_HEADER_ARRAY
171   void createPath(PathHistory *parentPath){
172     // Note that we are sending a message
173     thisMethodSentAMessage = true;
174     double timeNow = CmiWallTimer();
175     
176     if(parentPath != NULL){
177       //          CkPrintf("createPath() totalTime = %lf + %lf\n",(double)currentlyExecutingMsg->pathHistory.totalTime, (double)timeNow-timeEntryMethodStarted);
178       totalTime = parentPath->totalTime + (timeNow-timeEntryMethodStarted);
179       
180       for(int i=0;i<numEpIdxs;i++){
181         epIdxCount[i] = parentPath->epIdxCount[i];
182       }
183       for(int i=0;i<numArrayIds;i++){
184         arrayIdxCount[i] = parentPath->arrayIdxCount[i];
185       }
186       
187     }
188     else {
189       totalTime = 0.0;
190       
191       for(int i=0;i<numEpIdxs;i++){
192         epIdxCount[i] = 0;
193       } 
194       for(int i=0;i<numArrayIds;i++){
195         arrayIdxCount[i]=0;
196       }
197     }
198         
199   }
200 #endif
201       
202   void incrementEpIdxCount(int ep){
203     epIdxCount[ep]++;
204   }
205
206   void incrementArrayIdxCount(int arr){
207     arrayIdxCount[arr]++;
208   }
209       
210 };
211
212
213 #endif