Merge branch 'charm' of charmgit:charm into charm
[charm.git] / src / ck-cp / controlPoints.C
index 0eaca99b25b7441fc91a333dedae29b1e6fa0139..9698c61a7186b578a967a3ab74ca5009217251cb 100644 (file)
@@ -40,6 +40,13 @@ static void periodicProcessControlPoints(void* ptr, double currWallTime);
 /* readonly */ bool shouldGatherAll;
 
 
+
+/// The control point values to be used for the first few phases if the strategy doesn't choose to do something else.
+/// These probably come from the command line arguments, so are available only on PE 0
+std::map<std::string, int> defaultControlPointValues;
+
+
+
 typedef enum tuningSchemeEnum {RandomSelection, SimulatedAnnealing, ExhaustiveSearch, CriticalPathAutoPrioritization, UseBestKnownTiming, UseSteering, MemoryAware}  tuningScheme;
 
 
@@ -103,21 +110,16 @@ CkReductionMsg *idleTimeReduction(int nMsg,CkReductionMsg **msgs){
 /// A reduction type that combines idle, overhead, and memory measurements
 CkReduction::reducerType allMeasuresReductionType;
 /// A reducer that combines idle, overhead, and memory measurements
+#define ALL_REDUCTION_SIZE 12
 CkReductionMsg *allMeasuresReduction(int nMsg,CkReductionMsg **msgs){
-  double ret[7];
+  double ret[ALL_REDUCTION_SIZE];
   if(nMsg > 0){
-    CkAssert(msgs[0]->getSize()==7*sizeof(double));
+    CkAssert(msgs[0]->getSize()==ALL_REDUCTION_SIZE*sizeof(double));
     double *m=(double *)msgs[0]->getData();
-    ret[0]=m[0];
-    ret[1]=m[1];
-    ret[2]=m[2];
-    ret[3]=m[3];
-    ret[4]=m[4];
-    ret[5]=m[5];
-    ret[6]=m[6];
+    memcpy(ret, m, ALL_REDUCTION_SIZE*sizeof(double) );
   }
   for (int i=1;i<nMsg;i++) {
-    CkAssert(msgs[i]->getSize()==7*sizeof(double));
+    CkAssert(msgs[i]->getSize()==ALL_REDUCTION_SIZE*sizeof(double));
     double *m=(double *)msgs[i]->getData();
     // idle time (min/sum/max)
     ret[0]=min(ret[0],m[0]);
@@ -129,8 +131,15 @@ CkReductionMsg *allMeasuresReduction(int nMsg,CkReductionMsg **msgs){
     ret[5]=max(ret[5],m[5]);
     // mem usage (max)
     ret[6]=max(ret[6],m[6]);
+    // bytes per invocation for two types of entry methods
+    ret[7]+=m[7];
+    ret[8]+=m[8];
+    ret[9]+=m[9];
+    ret[10]+=m[10];
+    // Grain size (avg)
+    ret[11]+=m[11];
   }  
-  return CkReductionMsg::buildNew(7*sizeof(double),ret);   
+  return CkReductionMsg::buildNew(ALL_REDUCTION_SIZE*sizeof(double),ret);   
 }
 
 
@@ -269,10 +278,17 @@ controlPointManager::controlPointManager(){
       iss >> ips->memoryUsageMB;
       //     CkPrintf("Memory usage loaded from file: %d\n", ips.memoryUsageMB);
 
+      // Read idle time
       iss >> ips->idleTime.min;
       iss >> ips->idleTime.avg;
       iss >> ips->idleTime.max;
 
+      // read bytePerInvoke
+      iss >> ips->bytesPerInvoke;
+
+      // read grain size
+      iss >> ips->grainSize;
+
       // Read control point values
       for(int cp=0;cp<numControlPointNames;cp++){
        int cpvalue;
@@ -280,6 +296,12 @@ controlPointManager::controlPointManager(){
        ips->controlPoints.insert(make_pair(names[cp],cpvalue));
       }
 
+      // ignore median time
+      double mt;
+      iss >> mt;
+
+      // Read all times
+
       double time;
 
       while(iss >> time){
@@ -315,7 +337,7 @@ controlPointManager::controlPointManager(){
   }
 
   /// User can register a callback that is called when application should advance to next phase
-  void controlPointManager::setGranularityCallback(CkCallback cb, bool _frameworkShouldAdvancePhase){
+  void controlPointManager::setCPCallback(CkCallback cb, bool _frameworkShouldAdvancePhase){
     frameworkShouldAdvancePhase = _frameworkShouldAdvancePhase;
     granularityCallback = cb;
     haveGranularityCallback = true;
@@ -707,40 +729,53 @@ controlPointManager::controlPointManager(){
 
   /// Entry method called on all PEs to request CPU utilization statistics and memory usage
   void controlPointManager::requestAll(CkCallback cb){
-    const double i = localControlPointTracingInstance()->idleRatio();
-    const double o = localControlPointTracingInstance()->overheadRatio();
-    const double m = localControlPointTracingInstance()->memoryUsageMB();
-    
-    double data[3+3+1];
+    TraceControlPoints *t = localControlPointTracingInstance();
+
+    double data[ALL_REDUCTION_SIZE];
 
     double *idle = data;
     double *over = data+3;
     double *mem = data+6;
+    double *msgBytes = data+7;  
+    double *grainsize = data+11;  
 
+    const double i = t->idleRatio();
     idle[0] = i;
     idle[1] = i;
     idle[2] = i;
 
+    const double o = t->overheadRatio();
     over[0] = o;
     over[1] = o;
     over[2] = o;
 
+    const double m = t->memoryUsageMB();
     mem[0] = m;
+
+    msgBytes[0] = t->b2;
+    msgBytes[1] = t->b3;
+    msgBytes[2] = t->b2mlen;
+    msgBytes[3] = t->b3mlen;
+
+    grainsize[0] = t->grainSize();
     
     localControlPointTracingInstance()->resetAll();
 
-    contribute(7*sizeof(double),data,allMeasuresReductionType, cb);
+    contribute(ALL_REDUCTION_SIZE*sizeof(double),data,allMeasuresReductionType, cb);
   }
   
   /// All processors reduce their memory usages in requestIdleTime() to this method
   void controlPointManager::gatherAll(CkReductionMsg *msg){
+    CkAssert(msg->getSize()==ALL_REDUCTION_SIZE*sizeof(double));
     int size=msg->getSize() / sizeof(double);
-    CkAssert(size==7);
     double *data=(double *) msg->getData();
         
     double *idle = data;
     double *over = data+3;
     double *mem = data+6;
+    double *msgBytes = data+7;
+    double *granularity = data+11;
+
 
     //    std::string b = allData.toString();
 
@@ -754,6 +789,23 @@ controlPointManager::controlPointManager(){
       
       CkPrintf("Stored idle time min=%lf, mem=%lf in prevPhase=%p\n", (double)prevPhase->idleTime.min, (double)prevPhase->memoryUsageMB, prevPhase);
 
+      double bytesPerInvoke2 = msgBytes[2] / msgBytes[0];
+      double bytesPerInvoke3 = msgBytes[3] / msgBytes[1];
+
+      /** The average of the grain sizes on all PEs in us */
+      prevPhase->grainSize = (granularity[0] / (double)CkNumPes());
+
+      CkPrintf("Bytes Per Invokation 2 = %f\n", bytesPerInvoke2);
+      CkPrintf("Bytes Per Invokation 3 = %f\n", bytesPerInvoke3);
+
+      CkPrintf("Bytes Per us of work 2 = %f\n", bytesPerInvoke2/prevPhase->grainSize);
+      CkPrintf("Bytes Per us of work 3 = %f\n", bytesPerInvoke3/prevPhase->grainSize);
+
+      if(bytesPerInvoke2 > bytesPerInvoke3)
+       prevPhase->bytesPerInvoke = bytesPerInvoke2;
+      else
+       prevPhase->bytesPerInvoke = bytesPerInvoke3;
+
       //      prevPhase->print();
       // CkPrintf("prevPhase=%p number of timings=%d\n", prevPhase, prevPhase->times.size() );
 
@@ -909,8 +961,8 @@ public:
     int usec = (int)((time - (double)sec)*1000000.0);
     random_seed =  sec ^ usec;
 #endif
-
-
+    
+    
     double period;
     bool haveSamplePeriod = CmiGetArgDoubleDesc(args->argv,"+CPSamplePeriod", &period,"The time between Control Point Framework samples (in seconds)");
     if(haveSamplePeriod){
@@ -919,9 +971,9 @@ public:
     } else {
       controlPointSamplePeriod =  DEFAULT_CONTROL_POINT_SAMPLE_PERIOD;
     }
-
-
-
+    
+    
+    
     whichTuningScheme = RandomSelection;
 
 
@@ -941,6 +993,34 @@ public:
       whichTuningScheme = MemoryAware;
     }
 
+    char *defValStr = NULL;
+    if( CmiGetArgStringDesc(args->argv, "+CPDefaultValues", &defValStr, "Specify the default control point values used for the first couple phases") ){
+      CkPrintf("You specified default value string: %s\n", defValStr);
+      
+      // Parse the string, looking for commas
+     
+
+      char *tok = strtok(defValStr, ",");
+      while (tok) {
+       // split on the equal sign
+       int len = strlen(tok);
+       char *eqsign = strchr(tok, '=');
+       if(eqsign != NULL && eqsign != tok){
+         *eqsign = '\0';
+         char *cpname = tok;
+         std::string cpName(tok);
+         char *cpDefVal = eqsign+1;      
+         int v=-1;
+         if(sscanf(cpDefVal, "%d", &v) == 1){
+           CkPrintf("Command Line Argument Specifies that Control Point \"%s\" defaults to %d\n", cpname, v);
+           CkAssert(CkMyPe() == 0); // can only access defaultControlPointValues on PE 0
+           defaultControlPointValues[cpName] = v;
+         }
+       }
+       tok = strtok(NULL, ",");
+      }
+
+    }
 
     shouldGatherAll = false;
     shouldGatherMemoryUsage = false;
@@ -967,16 +1047,17 @@ public:
       loadDataFileAtStartup = true;
     }
 
+
     controlPointManagerProxy = CProxy_controlPointManager::ckNew();
   }
   ~controlPointMain(){}
 };
 
 /// An interface callable by the application.
-void registerGranularityChangeCallback(CkCallback cb, bool frameworkShouldAdvancePhase){
+void registerCPChangeCallback(CkCallback cb, bool frameworkShouldAdvancePhase){
   CkAssert(CkMyPe() == 0);
   CkPrintf("Application has registered a control point change callback\n");
-  controlPointManagerProxy.ckLocalBranch()->setGranularityCallback(cb, frameworkShouldAdvancePhase);
+  controlPointManagerProxy.ckLocalBranch()->setCPCallback(cb, frameworkShouldAdvancePhase);
 }
 
 /// An interface callable by the application.
@@ -1391,9 +1472,17 @@ int controlPoint(const char *name, int lb, int ub){
   
 
   if( phase_id < 4 ){
-    // For the first few phases, just use the lower bound. 
-    // This ensures that the ranges for all the control points known before we do anything fancy
+    // For the first few phases, just use the lower bound, or the default if one was provided 
+    // This ensures that the ranges for all the control points are known before we do anything fancy
     result = lb;
+
+
+    if(defaultControlPointValues.count(std::string(name)) > 0){
+      int v = defaultControlPointValues[std::string(name)];
+      CkPrintf("Startup phase using default value of %d for  \"%s\"\n", v, name);   
+      result = v;
+    }
+
   } else if(controlPointSpace.count(std::string(name)) == 0){
     // if this is the first time we've seen the CP, then return the lower bound
     result = lb;