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