Adding fortran interfaces to control point framework
[charm.git] / src / ck-cp / pathHistory.h
1
2 /**     @defgroup CriticalPathFramework Critical Path Detection
3
4         Usable for determining the critical paths in Charm++, Charisma, and SDAG programs. 
5 */
6
7 /** 
8
9     @addtogroup CriticalPathFramework
10     @{
11
12 */
13 #ifndef __PATH_HISTORY_H__
14 #define __PATH_HISTORY_H__
15
16 #include <vector>
17 #include <map>
18 #include <utility>
19 #include <cmath>
20 #include "PathHistory.decl.h"
21 #include "envelope.h"
22
23 #include <pup_stl.h>
24
25
26
27 void initializeCriticalPath(void);
28
29 void useThisCriticalPathForPriorities();
30 void automaticallySetMessagePriority(envelope *env);
31
32
33 class pathHistoryManager : public CBase_pathHistoryManager {
34  private:
35   std::map< std::pair<int,int>, int> criticalPathForPriorityCounts;
36   
37   pathInformationMsg *pathForUser; // A place to store the path while we perform a broadcast and reduction to save projections user events.
38
39  public:
40
41   pathHistoryManager();
42
43   pathHistoryManager(CkMigrateMessage *m){
44     CkAbort("pathHistoryManager does not have a working migration constructor."); 
45   }
46   
47   void pup(PUP::er &p) { 
48     CkAbort("pathHistoryManager cannot be pupped.");
49   } 
50
51
52
53  /** Trace perform a traversal backwards over the critical path specified as a 
54       table index for the processor upon which this is called.
55
56       If msg->saveAsProjectionsUserEvents is true then the resulting path will be 
57       broadcast to broadcastCriticalPathProjections() which will then call a 
58       reduction to criticalPathProjectionsDone() which will call the user supplied 
59       callback.
60       
61       Otherwise, the callback cb will be called with the resulting msg after the path has 
62       been traversed to its origin.  
63
64   */
65  void traceCriticalPathBackStepByStep(pathInformationMsg *msg);
66
67
68
69  void broadcastCriticalPathProjections(pathInformationMsg *msg);
70  void criticalPathProjectionsDone(CkReductionMsg *msg);
71
72  void saveCriticalPathForPriorities(pathInformationMsg *msg);
73
74
75  /// Traverse back and aquire the critical path to be used for automatic message prioritization
76  void useCriticalPathForPriories();
77
78  const std::map< std::pair<int,int>, int> & getCriticalPathForPriorityCounts() const { 
79    return criticalPathForPriorityCounts;
80  }
81   
82 };
83
84
85
86 /**
87    Augments the PathHistory in the envelope with the other necessary information
88    from the envelope. These should be derived from an incoming message.
89
90    These objects can then be used for storing of information about a path 
91    outside of the incoming message's header. 
92
93    These are used for:
94       1) information about the currently executing message
95       2) combining the maximum paths along a reduction
96       3) combining multiple paths in Charisma and SDAG programs
97
98    This can be constructed from an envelope.
99 */
100
101 class MergeablePathHistory {
102  public:
103   double timeEntryMethodStarted;
104
105   double preceding_path_time;
106
107   int sender_pe;  // for traversing back over the PAG
108   int sender_history_table_idx; // for traversing back over the PAG
109   
110   int local_ep;  // The locally executing EP
111   int local_arr; // The locally executing array
112
113 #ifdef USE_CRITICAL_PATH_HEADER_ARRAY
114  MergeablePathHistory(const envelope *env) 
115    : sender_pe(env->getSrcPe()), 
116     sender_history_table_idx(env->pathHistory.get_sender_history_table_idx()), 
117     local_ep(env->getEpIdx()),
118     local_arr(env->getArrayMgrIdx()),
119     preceding_path_time(env->pathHistory.getTime()),
120     timeEntryMethodStarted(0.0)
121       {
122         // No body
123       }
124 #else
125  MergeablePathHistory(const envelope *env) 
126    : sender_pe(env->getSrcPe()), 
127     local_ep(env->getEpIdx()),
128     local_arr(env->getArrayMgrIdx()),
129     timeEntryMethodStarted(0.0)
130       {
131         // No body
132       }
133 #endif
134
135   MergeablePathHistory() {
136     reset();
137   }
138   
139   void reset(){
140     sender_pe = -1; 
141     sender_history_table_idx = -1; 
142     local_ep = -1;
143     preceding_path_time = 0.0;
144     timeEntryMethodStarted = 0.0;
145   }
146   
147   void sanity_check(){
148     if(sender_history_table_idx > -1){ 
149       CkAssert(sender_pe < CkNumPes()); 
150       CkAssert(sender_pe >= -1);
151     }
152 /*     CkAssert(sender_history_table_idx < 100000); */
153 /*     CkAssert(sender_history_table_idx >= 0); */
154    
155 /*     CkAssert(local_ep < 500); */
156 /*     CkAssert(local_ep >= 0); */
157
158   }
159
160   void updateMax(const MergeablePathHistory& other){
161     if(preceding_path_time < other.preceding_path_time)
162       *this = other;
163   }
164
165
166   void updateMax(const envelope* env){
167     updateMax(MergeablePathHistory(env));
168   }
169   
170   double getTotalTime() const{
171     return preceding_path_time;
172   }
173
174   /// Write a description of the path into the beginning of the provided buffer. The buffer ought to be large enough.
175   void printHTMLToString(char* buf) const{
176 #ifdef USE_CRITICAL_PATH_HEADER_ARRAY
177     buf[0] = '\0';
178     sprintf(buf+strlen(buf), "MergeablePathHistory time=%lf send pe=%d idx=%d timeEntryStarted=%lf", (double)preceding_path_time, (int)sender_pe, (int)sender_history_table_idx, (double)timeEntryMethodStarted);
179 #endif
180   }
181
182   void setDebug100(){
183     preceding_path_time = 100.0;
184     CkPrintf("Setting path length to 100\n");
185   }
186
187 };
188
189
190 /** 
191     Stores information about the critical path in the table on each PE. 
192     The PAG can be constructed by merging these together.
193
194     These can be constructed from a MergeablePathHistory, and are assumed to refer to the local PE.
195 */
196 class PathHistoryTableEntry {
197 #ifdef USE_CRITICAL_PATH_HEADER_ARRAY
198
199  public:
200   int sender_pe;
201   int sender_history_table_idx;
202   int local_ep;
203   int local_arr;
204   int local_pe;
205
206  private:
207   double start_time;
208   double local_path_time;
209   double preceding_path_time;
210
211  public:
212   
213  PathHistoryTableEntry() 
214    : sender_pe(-1), 
215     sender_history_table_idx(-1), 
216     start_time(0.0),
217     local_path_time(0.0), 
218     preceding_path_time(0.0),     
219     local_ep(-1),
220     local_arr(-1),
221     local_pe(CkMyPe())
222       {
223         // No body
224       }
225   
226
227   /// Construct an entry for the table assuming the start time in input path is correct
228  PathHistoryTableEntry(const MergeablePathHistory& p, double localContribution = 0.0)
229     : sender_pe(p.sender_pe), 
230     sender_history_table_idx(p.sender_history_table_idx), 
231     local_path_time(localContribution), 
232     preceding_path_time(p.preceding_path_time),
233     start_time(p.timeEntryMethodStarted),
234     local_ep(p.local_ep),
235     local_arr(p.local_arr),
236     local_pe(CkMyPe())
237       {
238         // No body
239       }
240
241   /// Construct an entry with the actual start and end times for it.
242   PathHistoryTableEntry(const MergeablePathHistory& p, double start, double finish)
243     : sender_pe(p.sender_pe), 
244     sender_history_table_idx(p.sender_history_table_idx), 
245     local_path_time(finish-start), 
246     preceding_path_time(p.preceding_path_time),
247     start_time(start),
248     local_ep(p.local_ep),
249     local_arr(p.local_arr),
250     local_pe(CkMyPe())
251       {
252         // No body
253       }
254
255   void printInfo(char *prefix = ""){
256     CkPrintf("%s [sender pe=%d table idx=%d] [local path contribution=%lf ep=%d] [Time= %lf + %lf]\n", prefix,  
257              sender_pe, sender_history_table_idx, local_path_time, local_ep, preceding_path_time, local_path_time);  
258   }
259
260
261   /// Add an entry for this path history into the table, and write the corresponding information into the provided header
262   int addToTableAndEnvelope(envelope *env);
263   
264   /// Add an entry for this path history into the table. Returns the new index in the table.
265   int addToTable();
266   
267   /// Return the length of the path up to and including this entry
268   double getTotalTime(){
269     return local_path_time + preceding_path_time;
270   }
271
272   double get_start_time() const {return start_time;}
273   double get_local_path_time() const {return local_path_time;}
274   double get_preceding_path_time() const {return preceding_path_time;}
275 #endif
276
277 };
278
279
280
281 /// A debugging routine that outputs critical path info as Projections user events.
282 void  saveCurrentPathAsUserEvent(char* prefix="");
283
284 /// A debugging helper routine that sets the values in the currently executing message's path to 100
285 void setCurrentlyExecutingPathTo100(void);
286
287 /// A debugging routine that outputs critical path info as Projections user events.
288 void  printPathInMsg(void* msg);
289
290 /// A debugging routine that outputs critical path info as Projections user events.
291 void  printEPInfo();
292
293
294 /// Acquire the critical path and deliver it to the user supplied callback
295 void traceCriticalPathBack(CkCallback cb, bool saveToProjectionsTraces = false);
296
297
298 /// A message containing information about a path of entry method invocations. This contains an array of PathHistoryTableEntry objects
299 class pathInformationMsg : public CMessage_pathInformationMsg {
300  public:
301   PathHistoryTableEntry *history;
302   int historySize;
303   int saveAsProjectionsUserEvents;
304   CkCallback cb;
305   int table_idx;
306
307   void printme(){
308 #ifdef USE_CRITICAL_PATH_HEADER_ARRAY
309     CkPrintf("Path contains %d entries\n", historySize);
310     for(int i=historySize-1;i>=0;i--){
311       CkPrintf("\tPath Step %d: local_path_time=%lf arr=%d ep=%d starttime=%lf preceding path time=%lf pe=%d\n",i, history[i].get_local_path_time(),  history[i].local_arr, history[i].local_ep, history[i].get_start_time(), history[i].get_preceding_path_time(), history[i].local_pe);
312     }
313 #endif    
314   }
315   
316 };
317
318
319 CkpvExtern(MergeablePathHistory, currentlyExecutingPath); // The maximal incoming path for the node
320 CkpvExtern(double, timeEntryMethodStarted);
321
322
323 #ifdef USE_CRITICAL_PATH_HEADER_ARRAY
324 /** A table to store all the local nodes in the parallel dependency graph */
325 typedef std::map<int, PathHistoryTableEntry> PathHistoryTableType;
326 CkpvExtern(PathHistoryTableType, pathHistoryTable);
327 /** A counter that defines the new keys for the entries in the pathHistoryTable */
328 CkpvExtern(int, pathHistoryTableLastIdx);
329
330
331
332
333 // Reset the counts for the currently executing message. Cut the incoming path
334 extern void resetThisEntryPath();
335
336 extern void criticalPath_start(envelope * env); 
337 extern void criticalPath_send(envelope * sendingEnv);
338 extern void criticalPath_end();
339 extern void criticalPath_split(); 
340
341
342
343
344 /// Wrappers for Charm++ programs to use to annotate their program dependencies
345
346 /// Declare a MergeablePathHistory variable, whose name is mangled with the supplied parameter
347 #define MERGE_PATH_DECLARE(x) MergeablePathHistory merge_path_##x
348
349 /// Reset the merge_path variable
350 #define MERGE_PATH_RESET(x) merge_path_##x.reset()
351
352 /// Take the maximal path from the stored merge_path variable and the currently executing path. Put the result in currently executing path.
353 #define MERGE_PATH_MAX(x) merge_path_##x.updateMax(CkpvAccess(currentlyExecutingPath)); CkpvAccess(currentlyExecutingPath) = merge_path_##x; 
354
355
356
357 /// Declare a dynamic MergeablePathHistory variable. Each object can have many merge points stored in this single DECLARE.
358 #define MERGE_PATH_DECLARE_D(x) std::map<int,MergeablePathHistory> merge_path_D_##x
359
360 /// Reset the merge_path variable
361 #define MERGE_PATH_RESET_D(x,n) merge_path_D_##x[n].reset()
362
363 /// Delete the merge_path variable
364 #define MERGE_PATH_DELETE_D(x,n) merge_path_D_##x.erase(n)
365
366 /// Delete all entries in the merge_path variable
367 #define MERGE_PATH_DELETE_ALL_D(x) merge_path_D_##x.clear()
368
369 /// Take the maximal path from the stored merge_path variable and the currently executing path. Put the result in currently executing path.
370 #define MERGE_PATH_MAX_D(x,n) merge_path_D_##x[n].updateMax(CkpvAccess(currentlyExecutingPath)); CkpvAccess(currentlyExecutingPath) = merge_path_D_##x[n]; 
371
372
373
374 #else
375
376
377 /// Empty no-op version for when critical path history is not compiled in
378
379 #define MERGE_PATH_DECLARE(x) ;
380 #define MERGE_PATH_RESET(x) ;
381 #define MERGE_PATH_MAX(x) ;
382 #define MERGE_PATH_DECLARE_D(x) ;
383 #define MERGE_PATH_RESET_D(x,n) ;
384 #define MERGE_PATH_DELETE_D(x,n) ;
385 #define MERGE_PATH_DELETE_ALL_D(x) ;
386 #define MERGE_PATH_MAX_D(x,n) ;
387
388
389 #endif
390
391
392
393
394 /** @} */
395 #endif