Adding a ControlPointsNoTrace module that provides the control point interface but...
[charm.git] / src / ck-cp / arrayRedistributor.h
index 86d9e8e3faf3cb46a7251a05e70202a765868bcd..faf2a76f99e0c30dd1210e799eeea828ad240397 100644 (file)
@@ -8,9 +8,10 @@
 #define __ARRAYREDISTRIBUTOR_H__
 
 #include <vector>
+#include <list>
 #include <map>
 #include <cmath>
-#include "ControlPoints.decl.h"
+//#include "ControlPoints.decl.h"
 
 #include<pup_stl.h>
 
@@ -71,6 +72,10 @@ class redistributor2D: public CBase_redistributor2D {
   /// Is this array element active
   bool thisElemActive;
 
+  bool resizeGranulesHasBeenCalled;
+
+  CkVec<redistributor2DMsg *> bufferedMsgs;
+
  private:
 
 
@@ -102,6 +107,8 @@ class redistributor2D: public CBase_redistributor2D {
 
     p | dataRedistributedCallback;
 
+    p | resizeGranulesHasBeenCalled;
+
     p | x_chares;
     p | y_chares;
     p | data_width;
@@ -161,7 +168,6 @@ class redistributor2D: public CBase_redistributor2D {
     }
 
     //    CkPrintf("pup redistributor2D\n");
-
   } 
 
 
@@ -260,8 +266,10 @@ class redistributor2D: public CBase_redistributor2D {
 
 
   
-  // Convert a local column,row id (0 to mywidth-1, 0 to data_width-1) to the index in the padded array
+  // Convert a local column,row id (0 to mywidth()-1, 0 to myheight()-1) to the index in the padded array
   int local_to_padded(int x, int y){
+    CkAssert(thisElemActive);
+    CkAssert(x < (mywidth()+data_x_ghost) && x >= (0-data_x_ghost) && y < (myheight()+data_y_ghost) && y >= (0-data_y_ghost) );
     return (mywidth()+2*data_x_ghost)*(y+data_y_ghost)+x+data_x_ghost;
   }
 
@@ -337,6 +345,7 @@ class redistributor2D: public CBase_redistributor2D {
     data_y_ghost = y_ghosts;
     
     setDimensions(x_chares_, y_chares_);
+
   }
   
 
@@ -357,10 +366,12 @@ class redistributor2D: public CBase_redistributor2D {
   redistributor2D(){
     incoming_count = 0;
     fakeMemoryUsage = NULL;
+    CkAssert(bufferedMsgs.size() == 0);
   }
 
 
   redistributor2D(CkMigrateMessage*){
+    CkAssert(bufferedMsgs.size() == 0);
   }
 
 
@@ -368,6 +379,7 @@ class redistributor2D: public CBase_redistributor2D {
 #if DEBUG > 3 
    CkPrintf("redistributor 2D startup %03d,%03d\n", thisIndex.x, thisIndex.y);
 #endif
+
     contribute();
   }
   
@@ -386,11 +398,12 @@ class redistributor2D: public CBase_redistributor2D {
   
   // Called on all elements involved with the new granularity or containing part of the old data
   void resizeGranules(int new_active_chare_cols, int new_active_chare_rows){
-
 #if DEBUG>1
     CkPrintf("Resize Granules called for elem %d,%d\n", thisIndex.x, thisIndex.y);     
 #endif
 
+    resizeGranulesHasBeenCalled = true;
+
     const bool previouslyActive = thisElemActive;
     const int old_top = top_data_idx();
     const int old_left = left_data_idx();
@@ -399,7 +412,7 @@ class redistributor2D: public CBase_redistributor2D {
     const int old_myheight = myheight();
     const int old_mywidth = mywidth();
 
-    setDimensions(new_active_chare_cols, new_active_chare_rows);
+    setDimensions(new_active_chare_cols, new_active_chare_rows); // update dimensions & thisElemActive
     
     const int new_mywidth = mywidth();
     const int new_myheight = myheight();
@@ -493,8 +506,17 @@ class redistributor2D: public CBase_redistributor2D {
       
     }
 
+
+    // Call receiveTransposeData for any buffered messages.
+    int size = bufferedMsgs.size();
+    for(int i=0;i<size;i++){
+      redistributor2DMsg *msg = bufferedMsgs[i];
+      //     CkPrintf("Delivering buffered receiveTransposeData(msg=%p) i=%d\n", msg, i);
+      receiveTransposeData(msg); // this will delete the message
+    }
+    bufferedMsgs.removeAll();
+
     int newPe = (thisIndex.y * new_active_chare_cols + thisIndex.x) % CkNumPes();
-    
     if(newPe == CkMyPe()){
       //      CkPrintf("Keeping %02d , %02d on PE %d\n", thisIndex.x, thisIndex.y, newPe);
     }
@@ -502,21 +524,29 @@ class redistributor2D: public CBase_redistributor2D {
       // CkPrintf("Migrating %02d , %02d to PE %d\n", thisIndex.x, thisIndex.y, newPe);
       migrateMe(newPe);
     }
-    
+    // CANNOT CALL ANYTHING AFTER MIGRATE ME
   }
   
-
+  
   void continueToNextStep(){
 #if DEBUG > 2
     CkPrintf("Elem %d,%d is ready to continue\n", thisIndex.x, thisIndex.y);
 #endif
+
+    resizeGranulesHasBeenCalled = false;
+
     for(std::map<int,double*>::iterator diter =data_arrays.begin(); diter != data_arrays.end(); diter++){
       int which_array = diter->first;
       double *data = diter->second;
-      CkAssert( (data==NULL && !thisElemActive) || (data!=NULL && thisElemActive) );
-    }
-
+      if( ! ((data==NULL && !thisElemActive) || (data!=NULL && thisElemActive) )){
+       CkPrintf("[%d] ERROR: ! ((data==NULL && !thisElemActive) || (data!=NULL && thisElemActive) )",CkMyPe());
+       CkPrintf("[%d] ERROR: data=%p thisElemActive=%d  (perhaps continueToNextStep was called too soon)\n",CkMyPe(), data, (int)thisElemActive );
 
+       CkAbort("ERROR");       
+      }
+    }
+    
+    
 #if USE_EXTRAMEMORY
 #error NO USE_EXTRAMEMORY ALLOWED YET
     if(thisElemActive){
@@ -544,7 +574,19 @@ class redistributor2D: public CBase_redistributor2D {
 
 
 
+
+  
   void receiveTransposeData(redistributor2DMsg *msg){
+    
+    // buffer this message until resizeGranules Has Been Called
+    if(!resizeGranulesHasBeenCalled){
+      bufferedMsgs.push_back(msg);
+      //      CkPrintf("Buffering receiveTransposeData(msg=%p)\n", msg);
+      return;
+    }
+    
+    CkAssert(resizeGranulesHasBeenCalled);
+    
     int top_new = top_data_idx(thisIndex.y, msg->new_chare_rows);
     int bottom_new = bottom_data_idx(thisIndex.y, msg->new_chare_rows);
     int left_new = left_data_idx(thisIndex.x, msg->new_chare_cols);