Refactoring control point and critical path detection code.
[charm.git] / src / ck-cp / pathHistory.C
1 #include <charm++.h>
2 #include <iostream>
3 #include <fstream>
4 #include <string>
5 #include <map>
6 #include <set>
7 #include <vector>
8 #include <utility>
9
10 #include "ControlPoints.decl.h"
11 #include "trace-controlPoints.h"
12 #include "LBDatabase.h"
13 #include "controlPoints.h"
14 #include "pathHistory.h"
15 #include "arrayRedistributor.h"
16 #include <register.h> // for _entryTable
17
18
19 /**
20  *  \addtogroup CriticalPathFramework
21  *   @{
22  *
23  */
24
25 #ifdef USE_CRITICAL_PATH_HEADER_ARRAY
26
27
28 CkpvDeclare(MergeablePathHistory, currentlyExecutingPath); // The maximal incoming path for the node
29 CkpvDeclare(double, timeEntryMethodStarted);
30
31 void initializeCriticalPath(void){
32   CkpvInitialize(MergeablePathHistory, currentlyExecutingPath); // The maximal incoming path for the node
33   CkpvInitialize(double, timeEntryMethodStarted);
34   CkpvAccess(timeEntryMethodStarted) = 0.0;
35 }
36
37 void PathHistoryEnvelope::reset(){
38   totalTime = 0.0;
39   sender_history_table_idx = -1;
40 }
41
42   
43 void PathHistoryEnvelope::print() const {
44   CkPrintf("print() is not implemented\n");
45 }
46
47 /// Write a description of the path into the beginning of the provided buffer. The buffer ought to be large enough.
48
49   
50 void PathHistoryEnvelope::incrementTotalTime(double time){
51   totalTime += time;
52 }
53
54
55
56 void PathHistoryEnvelope::setDebug100(){
57   totalTime = 100.0;   
58 }
59
60
61 /// Add an entry for this path history into the table, and write the corresponding information into the outgoing envelope
62 int PathHistoryTableEntry::addToTableAndEnvelope(envelope *env){
63   // Add to table
64   int new_idx = addToTable();
65
66   // Fill in outgoing envelope
67   CkAssert(env != NULL);
68   env->pathHistory.set_sender_history_table_idx(new_idx);
69   env->pathHistory.setTime(local_path_time + preceding_path_time);
70
71   // Create a user event for projections
72   char *note = new char[4096];
73   sprintf(note, "addToTableAndEnvelope<br> ");
74   env->pathHistory.printHTMLToString(note+strlen(note));
75   traceUserSuppliedNote(note); // stores a copy of the string
76   delete[] note;
77   
78   return new_idx;
79 }
80   
81
82 /// Add an entry for this path history into the table. Returns the index in the table for it.
83 int PathHistoryTableEntry::addToTable(){
84   std::map<int, PathHistoryTableEntry> &table = controlPointManagerProxy.ckLocalBranch()->pathHistoryTable;
85   int &table_last_idx = controlPointManagerProxy.ckLocalBranch()->pathHistoryTableLastIdx;
86   int new_idx = table_last_idx++;
87   table[new_idx] = *this;
88   return new_idx;
89 }
90
91
92
93   
94 void resetThisEntryPath(void) {
95   CkpvAccess(currentlyExecutingPath).reset();
96 }
97
98
99 /// A debugging routine that outputs critical path info as user events.
100 void  saveCurrentPathAsUserEvent(char* prefix){
101   if(CkpvAccess(currentlyExecutingPath).getTotalTime() > 0.0){
102     //traceUserEvent(5020);
103
104     char *note = new char[4096];
105     sprintf(note, "%s<br> saveCurrentPathAsUserEvent()<br> ", prefix);
106     CkpvAccess(currentlyExecutingPath).printHTMLToString(note+strlen(note));
107     traceUserSuppliedNote(note); // stores a copy of the string
108     delete[] note;
109
110   } else {
111     traceUserEvent(5010);
112   }
113  
114 }
115
116
117 void setCurrentlyExecutingPathTo100(void){
118   CkpvAccess(currentlyExecutingPath).setDebug100();
119 }
120
121
122
123 /// A routine for printing out information along the critical path.
124 void traceCriticalPathBack(CkCallback cb){
125
126   pathInformationMsg *newmsg = new(0) pathInformationMsg;
127   newmsg->historySize = 0;
128   newmsg->cb = cb;
129   newmsg->table_idx = CkpvAccess(currentlyExecutingPath).sender_history_table_idx;
130   int pe = CkpvAccess(currentlyExecutingPath).sender_pe;
131   CkPrintf("Starting tracing of critical path from pe=%d table_idx=%d\n", pe,  CkpvAccess(currentlyExecutingPath).sender_history_table_idx);
132   CkAssert(pe < CkNumPes() && pe >= 0);
133   controlPointManagerProxy[pe].traceCriticalPathBack(newmsg);
134 }
135
136
137
138 // void  printPathInMsg(void* msg){
139 //   envelope *env = UsrToEnv(msg);
140 //   env->printPath();
141 // }
142
143
144
145 /// A debugging routine that prints the number of EPs for the program, and the size of the envelope's path fields
146 void  printEPInfo(){
147   CkPrintf("printEPInfo():\n");
148   CkPrintf("There are %d EPs\n", (int)_entryTable.size());
149   for (int epIdx=0;epIdx<_entryTable.size();epIdx++)
150     CkPrintf("EP %d is %s\n", epIdx, _entryTable[epIdx]->name);
151 }
152
153
154
155
156 /// Save information about the critical path contained in the message that is about to execute.
157 void criticalPath_start(envelope * env){ 
158 #ifdef USE_CRITICAL_PATH_HEADER_ARRAY
159 #if DEBUG
160   CkPrintf("criticalPath_start(envelope * env) srcpe=%d sender table idx=%d  time=%lf\n", env->getSrcPe(),  env->pathHistory.get_sender_history_table_idx(), env->pathHistory.getTotalTime() );
161 #endif
162
163   CkpvAccess(currentlyExecutingPath).sender_pe = env->getSrcPe();
164   CkpvAccess(currentlyExecutingPath).sender_history_table_idx = env->pathHistory.get_sender_history_table_idx();
165   CkpvAccess(currentlyExecutingPath).preceding_path_time = env->pathHistory.getTotalTime();
166
167   CkpvAccess(currentlyExecutingPath).sanity_check();
168   
169   CkpvAccess(currentlyExecutingPath).local_ep  = -1;
170   CkpvAccess(currentlyExecutingPath).local_arr = -1;
171
172   double now = CmiWallTimer();
173   CkpvAccess(currentlyExecutingPath).timeEntryMethodStarted = now;
174   CkpvAccess(timeEntryMethodStarted) = now;
175
176   switch(env->getMsgtype()) {
177   case ForArrayEltMsg:
178     //    CkPrintf("Critical Path Detection handling a ForArrayEltMsg\n");    
179     CkpvAccess(currentlyExecutingPath).local_ep = env->getsetArrayEp();
180     CkpvAccess(currentlyExecutingPath).local_arr = env->getArrayMgrIdx();
181     
182     break;
183
184   case ForNodeBocMsg:
185     //CkPrintf("Critical Path Detection handling a ForNodeBocMsg\n");    
186     break;
187
188   case ForChareMsg:
189     //CkPrintf("Critical Path Detection handling a ForChareMsg\n");        
190     break;
191
192   case ForBocMsg:
193     //CkPrintf("Critical Path Detection handling a ForBocMsg\n");    
194     break;
195
196   case ArrayEltInitMsg:
197     // Don't do anything special with these
198     break;
199
200   default:
201     CkPrintf("Critical Path Detection can't yet handle message type %d\n", (int)env->getMsgtype());
202   }
203   
204   
205
206   saveCurrentPathAsUserEvent("criticalPath_start()<br> ");
207
208
209 #endif
210 }
211
212
213 /// Modify the envelope of a message that is being sent for critical path detection and store an entry in a table on this PE.
214 void criticalPath_send(envelope * sendingEnv){
215 #ifdef USE_CRITICAL_PATH_HEADER_ARRAY
216 #if DEBUG
217   CkPrintf("criticalPath_send(envelope * sendingEnv)\n");
218 #endif
219   double now = CmiWallTimer();
220   PathHistoryTableEntry entry(CkpvAccess(currentlyExecutingPath), CkpvAccess(timeEntryMethodStarted), now);
221   entry.addToTableAndEnvelope(sendingEnv);
222   
223 #endif
224 }
225
226
227 /// Handle the end of the entry method in the critical path detection processes. This should create a forward dependency for the object.
228 void criticalPath_end(){
229 #ifdef USE_CRITICAL_PATH_HEADER_ARRAY
230   saveCurrentPathAsUserEvent("criticalPath_end()<br> ");
231
232   CkpvAccess(currentlyExecutingPath).reset();
233
234 #if DEBUG
235   CkPrintf("criticalPath_end()\n");
236 #endif
237
238 #endif
239 }
240
241
242
243 /// Split an entry method invocation into multiple logical tasks for the critical path analysis.
244 /// SDAG doen's break up the code in useful ways, so I'll make it add calls to this in the generated code.
245 void criticalPath_split(){
246   saveCurrentPathAsUserEvent("criticalPath_split()<br> ");
247
248   // save an entry in the table
249   double now = CmiWallTimer();
250   PathHistoryTableEntry entry(CkpvAccess(currentlyExecutingPath), now-CkpvAccess(timeEntryMethodStarted) );
251   int tableidx = entry.addToTable();
252
253   // end the old task
254
255   
256   // start the new task
257   CkpvAccess(currentlyExecutingPath).sender_pe = CkMyPe();
258   CkpvAccess(currentlyExecutingPath).sender_history_table_idx = tableidx;
259   CkpvAccess(currentlyExecutingPath).preceding_path_time = entry.getTotalTime();
260   CkpvAccess(currentlyExecutingPath).timeEntryMethodStarted = now;
261   CkpvAccess(timeEntryMethodStarted) = now;
262 }
263
264
265
266
267 #endif
268
269
270
271
272
273 /*! @} */
274