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