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