a7c4880517926be6446ef127accd2dcab1e8aed9
[charm.git] / src / ck-cp / controlPoints.h
1 /** 
2
3     A system for exposing application and runtime "control points" 
4     to the dynamic optimization framework.
5
6 */
7
8
9 #ifndef __CONTROLPOINTS_H__
10 #define __CONTROLPOINTS_H__
11
12 #include "conv-config.h"
13
14 #if CMK_WITH_CONTROLPOINT
15
16
17 #include "ControlPoints.decl.h"
18
19 #include <vector>
20 #include <map>
21 #include <cmath>
22 #include <pup_stl.h>
23 #include <string>
24 #include <set>
25 #include <cmath>
26 #include <math.h>
27 #include <iostream>
28 #include <iomanip>
29 #include <fstream>
30 #include <string>
31 #include <sstream>
32 #include <set>
33 #include <vector>
34 #include <utility>
35 #include <limits>
36 #include <algorithm>
37 #include <float.h>
38 #include <charm-api.h>
39
40 #include "LBDatabase.h"
41 #include "arrayRedistributor.h"
42 #include "pathHistory.h" 
43
44
45 #include <cp_effects.h>
46
47 /**
48  * \addtogroup ControlPointFramework
49  *   @{
50  */
51
52 #define DEBUG 0
53
54 /* readonly */ extern CProxy_controlPointManager controlPointManagerProxy;
55 /* readonly */ extern int random_seed;
56 /* readonly */ extern long controlPointSamplePeriod;
57 /* readonly */ extern int whichTuningScheme;
58 /* readonly */ extern bool writeDataFileAtShutdown;
59 /* readonly */ extern bool shouldFilterOutputData;
60 /* readonly */ extern bool loadDataFileAtStartup;
61 /* readonly */ extern char CPDataFilename[512];
62
63
64
65 void registerCPChangeCallback(CkCallback cb, bool frameworkShouldAdvancePhase);
66
67 void setFrameworkAdvancePhase(bool frameworkShouldAdvancePhase);
68
69
70 void registerControlPointTiming(double time);
71
72 /// Called once each application step. Can be used instead of registerControlPointTiming()
73 void controlPointTimingStamp();
74 FDECL void FTN_NAME(CONTROLPOINTTIMINGSTAMP,controlpointtimingstamp)();
75
76
77 /// The application specifies that it is ready to proceed to a new set of control point values.
78 /// This should be called after registerControlPointTiming()
79 /// This should be called before calling controlPoint()
80 void gotoNextPhase();
81 FDECL void FTN_NAME(GOTONEXTPHASE,gotonextphase)();
82
83 /// Return an integral power of 2 between c1 and c2
84 /// The value returned will likely change between subsequent invocations
85 int controlPoint2Pow(const char *name, int c1, int c2);
86
87 /// Return an integer between lb and ub inclusive
88 /// The value returned will likely change between subsequent invocations
89 int controlPoint(const char *name, int lb, int ub);
90
91 /// A fortran callable one. I couldn't figure out how to pass a string from fortran to C++ yet
92 /// So far fortran can only have one control point
93 FDECL int FTN_NAME(CONTROLPOINT,controlpoint)(CMK_TYPEDEF_INT4 *lb, CMK_TYPEDEF_INT4 *ub);
94
95
96 /// Return an integer from the provided vector of values
97 /// The value returned will likely change between subsequent invocations
98 int controlPoint(const char *name, std::vector<int>& values);
99
100 /// Write output data to disk. Callable from user program (for example, to periodically flush to disk if program might run out of time, or NAMD)
101 void ControlPointWriteOutputToDisk();
102
103 /// The application specifies that it is ready to proceed to a new set of control point values.
104 /// This should be called after registerControlPointTiming()
105 /// This should be called before calling controlPoint()
106 void gotoNextPhase();
107
108
109
110
111 /// A message used for signaling changes in control point values
112 class controlPointMsg : public CMessage_controlPointMsg {
113  public:
114   char *data;
115 };
116
117
118
119
120
121 /// A container that stores idle time statistics (min/max/avg etc.)
122 class idleTimeContainer {
123 public:
124   double min;
125   double avg;
126   double max;
127   
128   idleTimeContainer(){
129     min = -1.0;
130     max = -1.0;
131     avg = -1.0;
132   }
133   
134   bool isValid() const{
135     return (min >= 0.0 && avg >= min && max >= avg && max <= 1.0);
136   }
137   
138   void print() const{
139     if(isValid())
140       CkPrintf("[%d] Idle Time is Min=%.2lf%% Avg=%.2lf%% Max=%.2lf%%\n", CkMyPe(), min*100.0, avg*100.0, max*100.0);    
141     else
142       CkPrintf("[%d] Idle Time is invalid\n", CkMyPe(), min*100.0, avg*100.0, max*100.0);
143   }
144   
145 }; 
146
147
148 /// A container that stores overhead statistics (min/max/avg etc.)
149 class overheadContainer {
150 public:
151   double min;
152   double avg;
153   double max;
154   
155   overheadContainer(){
156     min = -1.0;
157     max = -1.0;
158     avg = -1.0;
159   }
160   
161   bool isValid() const{
162     return (min >= 0.0 && avg >= min && max >= avg && max <= 1.0);
163   }
164   
165   void print() const{
166     if(isValid())
167       CkPrintf("[%d] Overhead Time is Min=%.2lf%% Avg=%.2lf%% Max=%.2lf%%\n", CkMyPe(), min*100.0, avg*100.0, max*100.0);    
168     else
169       CkPrintf("[%d] Overhead Time is invalid\n", CkMyPe(), min*100.0, avg*100.0, max*100.0);
170   }
171   
172 }; 
173
174
175
176 /// Stores data for a phase (a time range in which a single set of control point values is used).
177 /// The data stored includes the control point values, a set of timings registered by the application, 
178 /// The critical paths detected, the max memory usage, and the idle time.
179 class instrumentedPhase {
180 public:
181   std::map<std::string,int> controlPoints; // The control point values for this phase(don't vary within the phase)
182   std::vector<double> times;  // A list of times observed for iterations in this phase
183
184 #ifdef USE_CRITICAL_PATH_HEADER_ARRAY
185   std::vector<PathHistoryTableEntry> criticalPaths;
186 #endif
187   
188   double memoryUsageMB;
189
190   idleTimeContainer idleTime;
191   overheadContainer overheadTime;
192
193
194   /** Approximately records the average message size for an entry method. */
195   double bytesPerInvoke;
196
197   /** Records the average grain size (might be off a bit due to non application entry methods), in seconds */
198   double grainSize;
199
200
201   instrumentedPhase(){
202     memoryUsageMB = -1.0;
203     grainSize = -1.0;
204     bytesPerInvoke = -1.0;
205   }
206   
207   void clear(){
208     controlPoints.clear();
209     times.clear();
210     memoryUsageMB = -1.0;
211     grainSize = -1.0;
212     bytesPerInvoke = -1.0;
213     //    criticalPaths.clear();
214   }
215
216   // Provide a previously computed value, or a value from a previous run
217   bool haveValueForName(const char* name){
218     std::string n(name);
219     return (controlPoints.count(n)>0);
220   }
221
222   void operator=(const instrumentedPhase& p){
223     controlPoints = p.controlPoints;
224     times = p.times;
225     memoryUsageMB = p.memoryUsageMB;
226   }
227
228
229
230   bool operator<(const instrumentedPhase& p){
231     CkAssert(hasSameKeysAs(p)); 
232     std::map<std::string,int>::iterator iter1 = controlPoints.begin();
233     std::map<std::string,int>::const_iterator iter2 = p.controlPoints.begin();
234     for(;iter1 != controlPoints.end() && iter2 != p.controlPoints.end(); iter1++, iter2++){
235       if(iter1->second < iter2->second){
236         return true;
237       }
238     }
239     return false;
240   }
241
242
243   // Determines if the control point values and other information exists
244   bool hasValidControlPointValues(){
245     std::map<std::string,int>::iterator iter;
246     for(iter = controlPoints.begin();iter != controlPoints.end(); iter++){
247       if(iter->second == -1){ 
248         return false; 
249       }  
250     }
251     return true;
252   }
253
254   
255 //   int medianCriticalPathIdx() const{
256 //     // Bubble sort the critical path indices by Time
257 //     int numPaths = criticalPaths.size();
258 //     if(numPaths>0){
259 //       int *sortedPaths = new int[numPaths];
260 //       for(int i=0;i<numPaths;i++){
261 //      sortedPaths[i] = i;
262 //       }
263       
264 //       for(int j=0;j<numPaths;j++){
265 //      for(int i=0;i<numPaths-1;i++){
266 //        if(criticalPaths[sortedPaths[i]].getTotalTime() < criticalPaths[sortedPaths[i+1]].getTotalTime()){
267 //          // swap sortedPaths[i], sortedPaths[i+1]
268 //          int tmp = sortedPaths[i+1];
269 //          sortedPaths[i+1] = sortedPaths[i];
270 //          sortedPaths[i] = tmp;
271 //        }
272 //      }
273 //       }
274 //       int result = sortedPaths[numPaths/2];
275 //       delete[] sortedPaths;
276 //       return result;
277 //     } else {
278 //       return 0;
279 //     }
280 //   }
281
282
283
284   bool operator==(const instrumentedPhase& p){
285     CkAssert(hasSameKeysAs(p));
286     std::map<std::string,int>::iterator iter1 = controlPoints.begin();
287     std::map<std::string,int>::const_iterator iter2 = p.controlPoints.begin();
288     for(;iter1 != controlPoints.end() && iter2 != p.controlPoints.end(); iter1++, iter2++){ 
289       if(iter1->second != iter2->second){ 
290         return false; 
291       }  
292     }
293     return true;
294   }
295
296   /// Verify the names of the control points are consistent
297   /// note: std::map stores the pairs in a sorted order based on their first component 
298   bool hasSameKeysAs(const instrumentedPhase& p){
299     
300     if(controlPoints.size() != p.controlPoints.size())
301       return false;
302
303     std::map<std::string,int>::iterator iter1 = controlPoints.begin(); 
304     std::map<std::string,int>::const_iterator iter2 = p.controlPoints.begin(); 
305
306     for(;iter1 != controlPoints.end() && iter2 != p.controlPoints.end(); iter1++, iter2++){  
307       if(iter1->first != iter2->first)
308         return false;
309     } 
310
311     return true; 
312   }
313
314
315   void addAllNames(std::set<std::string> names_) {
316     
317     std::set<std::string> names = names_;
318     
319     // Remove all the names that we already have
320     std::map<std::string,int>::iterator iter;
321     
322     for(iter = controlPoints.begin(); iter != controlPoints.end(); iter++){
323       names.erase(iter->first);
324     }
325     
326     // Add -1 values for each name we didn't find
327     std::set<std::string>::iterator iter2;
328     for(iter2 = names.begin(); iter2 != names.end(); iter2++){
329       controlPoints.insert(std::make_pair(*iter2,-1));
330       CkPrintf("One of the datasets was missing a value for %s, so -1 was used\n", iter2->c_str());
331     }
332
333   }
334   
335   
336   
337   void print() const {
338     std::map<std::string,int>::const_iterator iter;
339
340     if(controlPoints.size() == 0){
341       CkPrintf("no control point values found\n");
342     }
343     
344     for(iter = controlPoints.begin(); iter != controlPoints.end(); iter++){
345       const std::string name = iter->first;
346       const int val = iter->second;
347       CkPrintf("%s ---> %d\n",  name.c_str(),  val);
348     } 
349     
350   }
351
352   /** Determine the median time for this phase */
353   double medianTime(){
354     std::vector<double> sortedTimes = times;
355     std::sort(sortedTimes.begin(), sortedTimes.end());
356     if(sortedTimes.size()>0){
357         return sortedTimes[sortedTimes.size() / 2];
358     } else {
359         CkAbort("Cannot compute medianTime for empty sortedTimes vector");
360         return -1;
361     }
362   }
363
364   
365 };
366
367
368 /// Stores and manipulate all known instrumented phases. One instance of this exists on each PE in its local controlPointManager
369 class instrumentedData {
370 public:
371
372   /// Stores all known instrumented phases(loaded from file, or from this run)
373   std::vector<instrumentedPhase*> phases;
374
375   /// get control point names for all phases
376   std::set<std::string> getNames(){
377     std::set<std::string> names;
378     
379     std::vector<instrumentedPhase*>::iterator iter;
380     for(iter = phases.begin();iter!=phases.end();iter++) {
381       
382       std::map<std::string,int>::iterator iter2;
383       for(iter2 = (*iter)->controlPoints.begin(); iter2 != (*iter)->controlPoints.end(); iter2++){
384         names.insert(iter2->first);
385       }
386       
387     }  
388     return names;
389
390   } 
391
392
393   void cleanupNames(){
394     std::set<std::string> names = getNames();
395     
396     std::vector<instrumentedPhase*>::iterator iter;
397     for(iter = phases.begin();iter!=phases.end();iter++) {
398       (*iter)->addAllNames(names);
399     }
400   }
401
402
403   /// Remove one phase with invalid control point values if found
404   bool filterOutOnePhase(){
405 #if 1
406     // Note: calling erase on a vector will invalidate any iterators beyond the deletion point
407     std::vector<instrumentedPhase*>::iterator iter;
408     for(iter = phases.begin(); iter != phases.end(); iter++) {
409       if(! (*iter)->hasValidControlPointValues()  || (*iter)->times.size()==0){
410         // CkPrintf("Filtered out a phase with incomplete control point values\n");
411         phases.erase(iter);
412         return true;
413       } else {
414         //      CkPrintf("Not filtering out some phase with good control point values\n");
415       }
416     }
417 #endif
418     return false;
419   }
420   
421   /// Drop any phases that do not contain timings or control point values
422   void filterOutIncompletePhases(){
423     bool done = false;
424     while(filterOutOnePhase()){
425       // do nothing
426     }
427   }
428
429
430   std::string toString(){
431     std::ostringstream s;
432
433     // HEADER:
434     s << "# HEADER:\n";
435     s << "# Data for use with Isaac Dooley's Control Point Framework\n";
436     s << "# Number of instrumented timings in this file:\n"; 
437     s << phases.size() << "\n" ;
438     
439     if(phases.size() > 0){
440       
441       std::map<std::string,int> &ps = phases[0]->controlPoints; 
442       std::map<std::string,int>::iterator cpiter;
443
444       // SCHEMA:
445       s << "# SCHEMA:\n";
446       s << "# number of named control points:\n";
447       s << ps.size() << "\n";    
448       for(cpiter = ps.begin(); cpiter != ps.end(); cpiter++){
449         s << cpiter->first << "\n";
450       }
451       
452       // DATA:
453       s << "# DATA:\n";
454       s << "# There are " << ps.size()  << " control points\n";
455       s << "# number of recorded phases: " << phases.size() << "\n";
456       
457       s << "# Memory (MB)\tIdle Min\tIdle Avg\tIdle Max\tOverhead Min\tOverhead Avg\tOverhead Max\tByte Per Invoke\tGrain Size\t";
458       for(cpiter = ps.begin(); cpiter != ps.end(); cpiter++){
459         s << cpiter->first << "\t";
460       }
461       s << "Median Timing\tTimings\n";
462       
463    
464       std::vector<instrumentedPhase*>::iterator runiter;
465       for(runiter=phases.begin();runiter!=phases.end();runiter++){
466         
467         // Print the memory usage
468         s << (*runiter)->memoryUsageMB << "\t"; 
469
470         s << (*runiter)->idleTime.min << "\t" << (*runiter)->idleTime.avg << "\t" << (*runiter)->idleTime.max << "\t";
471         s << (*runiter)->overheadTime.min << "\t" << (*runiter)->overheadTime.avg << "\t" << (*runiter)->overheadTime.max << "\t";
472
473
474         s << (*runiter)->bytesPerInvoke << "\t";
475
476         s << (*runiter)->grainSize << "\t";
477
478
479         // Print the control point values
480         for(cpiter = (*runiter)->controlPoints.begin(); cpiter != (*runiter)->controlPoints.end(); cpiter++){ 
481           s << cpiter->second << "\t"; 
482         }
483
484         // Print the median time
485         if((*runiter)->times.size()>0){
486                 s << (*runiter)->medianTime() << "\t";
487         } else {
488                 s << "-1\t";
489         }
490
491         // Print the times
492         std::vector<double>::iterator titer;
493         for(titer = (*runiter)->times.begin(); titer != (*runiter)->times.end(); titer++){
494           s << *titer << " ";
495         }
496
497         s << "\n";
498         
499       }
500  
501     }
502
503     return s.str();
504     
505   }
506
507
508   /// Verify that all our phases of data have the same sets of control point names
509   void verify(){
510     if(phases.size() > 1){
511       instrumentedPhase *firstpoint = phases[0];
512       std::vector<instrumentedPhase*>::iterator iter;
513       for(iter = phases.begin();iter!=phases.end();iter++){
514         CkAssert( firstpoint->hasSameKeysAs(*(*iter)));
515       }  
516     } 
517   }
518
519
520   // Find the fastest time from previous runs
521   instrumentedPhase* findBest(){
522     CkAssert(phases.size()>1);
523
524     double total_time = 0.0; // total for all times
525     int total_count = 0;
526
527     instrumentedPhase * best_phase;
528
529 #if OLDMAXDOUBLE
530     double best_phase_avgtime = std::numeric_limits<double>::max();
531 #else
532     double best_phase_avgtime = DBL_MAX;
533 #endif
534
535     int valid_phase_count = 0;
536
537     std::vector<instrumentedPhase*>::iterator iter;
538     for(iter = phases.begin();iter!=phases.end();iter++){
539       if((*iter)->hasValidControlPointValues()){
540         valid_phase_count++;
541
542         double total_for_phase = 0.0;
543         int phase_count = 0;
544
545         // iterate over all times for this control point configuration
546         std::vector<double>::iterator titer;
547         for(titer = (*iter)->times.begin(); titer != (*iter)->times.end(); titer++){
548           total_count++;
549           total_time += *titer;
550           total_for_phase += *titer;
551           phase_count ++;
552         }
553
554         double phase_average_time = total_for_phase / (double)phase_count;
555
556         if(phase_average_time  < best_phase_avgtime){
557           best_phase = *iter;
558           best_phase_avgtime = phase_average_time; 
559         }
560
561       }
562     }
563     
564     CkAssert(total_count > 0);
565
566     double avg = total_time / total_count;
567
568     if(CkMyPe() == 0){
569       CkPrintf("Best average time for a phase was %.1lf\n", best_phase_avgtime);
570       CkPrintf("Mean time for all %d times in the %d valid recorded phases was %.1lf\n", total_count, valid_phase_count, avg );
571     }
572
573     // Compute standard deviation
574     double sumx=0.0;
575     for(iter = phases.begin();iter!=phases.end();iter++){
576       if((*iter)->hasValidControlPointValues()){
577         std::vector<double>::iterator titer;
578         for(titer = (*iter)->times.begin(); titer != (*iter)->times.end(); titer++){
579           sumx += (avg - *titer)*(avg - *titer);
580         } 
581       }
582     }
583     
584     double std_dev = sqrt(sumx / total_count);
585
586     if(CkMyPe() == 0){
587       CkPrintf("Standard Deviation for previous runs was %.2lf   or %.1lf%% of mean\n", std_dev, std_dev/avg*100.0);
588       CkPrintf("The best phase average time was %.1lf%% faster than the mean\n", (avg-best_phase_avgtime)/avg*100.0);
589
590     }
591
592     return best_phase;
593   }
594   
595 };
596
597
598 /** A class that implements the Nelder Mead Simplex Optimization Algorithm */
599 class simplexScheme {
600 private:
601         /** The states used by the Nelder Mead Simplex Algorithm. 
602             The transitions between these states are displayed in the NelderMeadStateDiagram.pdf diagram.
603         */
604         typedef enum simplexStateEnumT {beginning, reflecting, expanding, contracting, doneExpanding, stillContracting}  simplexStateT;
605
606         /// The indices into the allData->phases that correspond to the current simplex used one of the tuning schemes.
607         std::set<int> simplexIndices;
608         simplexStateT simplexState;
609
610          /// Reflection coefficient
611         double alpha;
612         // Contraction coefficient
613         double beta;
614         // Expansion coefficient
615         double gamma;
616
617
618         /// The first phase that was used by the this scheme. This helps us ignore a few startup phases that are out of our control.
619         int firstSimplexPhase;
620
621         // Worst performing point in the simplex
622         int worstPhase;
623         double worstTime;
624         std::vector<double> worst; // p_h
625
626         // Centroid of remaining points in the simplex
627         std::vector<double> centroid;
628
629         // Best performing point in the simplex
630         int bestPhase;
631         double bestTime;
632         std::vector<double> best;
633
634         // P*
635         std::vector<double> P;
636         int pPhase;
637
638         // P**
639         std::vector<double> P2;
640         int p2Phase;
641
642         // A set of phases for which (P_i+P_l)/2 ought to be evaluated
643         std::set<int> stillMustContractList;
644
645         bool useBestKnown;
646
647         void computeCentroidBestWorst(std::map<std::string, std::pair<int,int> > & controlPointSpace, std::map<std::string,int> &newControlPoints, const int phase_id, instrumentedData &allData);
648
649         void doReflection(std::map<std::string, std::pair<int,int> > & controlPointSpace, std::map<std::string,int> &newControlPoints, const int phase_id, instrumentedData &allData);
650         void doExpansion(std::map<std::string, std::pair<int,int> > & controlPointSpace, std::map<std::string,int> &newControlPoints, const int phase_id, instrumentedData &allData);
651         void doContraction(std::map<std::string, std::pair<int,int> > & controlPointSpace, std::map<std::string,int> &newControlPoints, const int phase_id, instrumentedData &allData);
652
653
654         std::vector<double> pointCoords(instrumentedData &allData, int i);
655
656                 inline int keepInRange(int v, int lb, int ub){
657                         if(v < lb)
658                                 return lb;
659                         if(v > ub)
660                                 return ub;
661                         return v;
662                 }
663
664                 void printSimplex(instrumentedData &allData){
665                         char s[2048];
666                         s[0] = '\0';
667                         for(std::set<int>::iterator iter = simplexIndices.begin(); iter != simplexIndices.end(); ++iter){
668                                 sprintf(s+strlen(s), "%d: ", *iter);
669
670                                 for(std::map<std::string,int>::iterator citer = allData.phases[*iter]->controlPoints.begin(); citer != allData.phases[*iter]->controlPoints.end(); ++citer){
671                                         sprintf(s+strlen(s), " %d", citer->second);
672                                 }
673
674                                 sprintf(s+strlen(s), "\n");
675                         }
676                         CkPrintf("Current simplex is:\n%s\n", s);
677                 }
678
679 public:
680
681         simplexScheme() :
682                 simplexState(beginning),
683                 alpha(1.0), beta(0.5), gamma(2.0),
684                 firstSimplexPhase(-1),
685                 useBestKnown(false)
686         {
687                 // Make sure the coefficients are reasonable
688                 CkAssert(alpha >= 0);
689                 CkAssert(beta >= 0.0 && beta <= 1.0);
690                 CkAssert(gamma >= 1.0);
691         }
692
693         void adapt(std::map<std::string, std::pair<int,int> > & controlPointSpace, std::map<std::string,int> &newControlPoints, const int phase_id, instrumentedData &allData);
694
695 };
696
697
698
699 class controlPointManager : public CBase_controlPointManager {
700 public:
701     
702   instrumentedData allData;
703   
704   /// The lower and upper bounds for each named control point
705   std::map<std::string, std::pair<int,int> > controlPointSpace;
706
707   /// A set of named control points whose values cannot change within a single run of an application
708   std::set<std::string> staticControlPoints;
709
710   /// @deprecated Sets of entry point ids that are affected by some named control points
711   std::map<std::string, std::set<int> > affectsPrioritiesEP;
712   /// @deprecated Sets of entry array ids that are affected by some named control points
713   std::map<std::string, std::set<int> > affectsPrioritiesArray;
714
715   
716   /// The control points to be used in the next phase. In gotoNextPhase(), these will be used
717   std::map<std::string,int> newControlPoints;
718   int generatedPlanForStep;
719
720   simplexScheme s;
721
722   
723   /// A user supplied callback to call when control point values are to be changed
724   CkCallback controlPointChangeCallback;
725   bool haveControlPointChangeCallback;
726   bool frameworkShouldAdvancePhase;
727   
728   int phase_id;
729
730   bool alreadyRequestedMemoryUsage;
731   bool alreadyRequestedIdleTime;
732   bool alreadyRequestedAll;
733
734   bool exitWhenReady;
735
736
737   controlPointManager();
738      
739   ~controlPointManager();
740
741   void pup(PUP::er &p);
742   
743  controlPointManager(CkMigrateMessage* m) : CBase_controlPointManager(m) {
744     // CkPrintf("Warning: control point framework likely won't work after checkpoint restart, please fix this problem if you need the functionality.");
745   }
746
747
748   /// Loads the previous run data file
749   void loadDataFile();
750
751   /// Add the current data to allData and output it to a file
752   void writeDataFile();
753
754   /// User can register a callback that is called when application should advance to next phase
755   void setCPCallback(CkCallback cb, bool _frameworkShouldAdvancePhase);
756
757   void setFrameworkAdvancePhase(bool _frameworkShouldAdvancePhase);
758
759   /// Called periodically by the runtime to handle the control points
760   /// Currently called on each PE
761   void processControlPoints();
762   
763   /// Determine if any control point is known to affect an entry method
764   bool controlPointAffectsThisEP(int ep);
765   
766   /// Determine if any control point is known to affect a chare array  
767   bool controlPointAffectsThisArray(int array);
768
769   /// Generate a plan (new control point values) once per phase
770   void generatePlan();
771
772   /// The data for the current phase
773   instrumentedPhase *currentPhaseData();
774
775   /// The data from the previous phase
776   instrumentedPhase *previousPhaseData();
777
778   /// The data from two phases back
779   instrumentedPhase *twoAgoPhaseData();
780
781   /// Called by either the application or the Control Point Framework to advance to the next phase  
782   void gotoNextPhase();
783
784   /// An application uses this to register an instrumented timing for this phase
785   void setTiming(double time);
786
787   /// Check to see if we are in the shutdown process, and handle it appropriately.
788   void checkForShutdown();
789
790   /// Start shutdown procedures for the controlPoints module(s). CkExit will be called once all outstanding operations have completed (e.g. waiting for idle time & memory usage to be gathered)
791   void exitIfReady();
792
793   /// All outstanding operations have completed, so do the shutdown now. First write files to disk, and then call CkExit().
794   void doExitNow();
795
796   /// Write data to disk (when needed), likely at exit
797   void writeOutputToDisk();
798
799
800   /// Entry method called on all PEs to request memory usage
801   void requestMemoryUsage(CkCallback cb);
802   /// All processors reduce their memory usages to this method
803   void gatherMemoryUsage(CkReductionMsg *msg);
804
805
806   /// Entry method called on all PEs to request memory usage
807   void requestIdleTime(CkCallback cb);
808   /// All processors reduce their memory usages in requestIdleTime() to this method
809   void gatherIdleTime(CkReductionMsg *msg);
810   
811
812   /// Entry method called on all PEs to request Idle, Overhead, and Memory measurements
813   void requestAll(CkCallback cb);
814   /// All processors reduce their memory usages in requestIdleTime() to this method
815   void gatherAll(CkReductionMsg *msg);
816   
817
818 /*   /// Inform the control point framework that a named control point affects the priorities of some array   */
819 /*   void associatePriorityArray(const char *name, int groupIdx); */
820   
821 /*   /// Inform the control point framework that a named control point affects the priority of some entry method */
822 /*   void associatePriorityEntry(const char *name, int idx); */
823   
824
825
826 };
827
828 #endif
829
830 /** @} */
831 #endif