00001 
00014 
00015 #include "RefineSwapLB.h"
00016 #include "ckgraph.h"
00017 #include <algorithm>
00018 #include <iostream>
00019 
00020 using std::cout;
00021 using std::endl;
00022 
00023 extern int quietModeRequested;
00024 
00025 CreateLBFunc_Def(RefineSwapLB,
00026     "always assign the heaviest obj onto lightest loaded processor.")
00027 
00028 RefineSwapLB::RefineSwapLB(const CkLBOptions &opt): CBase_RefineSwapLB(opt)
00029 {
00030   lbname = "RefineSwapLB";
00031   if (CkMyPe()==0 && !quietModeRequested)
00032     CkPrintf("CharmLB> RefineSwapLB created.\n");
00033 }
00034 
00035 bool RefineSwapLB::QueryBalanceNow(int _step)
00036 {
00037   
00038   return true;
00039 }
00040 
00041 class RefineSwapLB::ProcLoadGreater {
00042   public:
00043     bool operator()(ProcInfo p1, ProcInfo p2) {
00044       return (p1.getTotalLoad() > p2.getTotalLoad());
00045     }
00046 };
00047 
00048 class RefineSwapLB::ProcLoadGreaterIndex {
00049  public: 
00050   ProcLoadGreaterIndex(ProcArray * parr) : parr(parr) {}
00051   bool operator()(int lhs, int rhs) {
00052     return (parr->procs[lhs].getTotalLoad() < parr->procs[rhs].getTotalLoad());
00053   }
00054  private:
00055   ProcArray *parr;
00056 };
00057 
00058 class RefineSwapLB::ObjLoadGreater {
00059   public:
00060     ObjLoadGreater(ObjGraph* ogr) : ogr(ogr) {}
00061     bool operator()(int lhs, int rhs) {
00062       return (ogr->vertices[lhs].getVertexLoad() < ogr->vertices[rhs].getVertexLoad());
00063     }
00064   private:
00065     ObjGraph* ogr;
00066 };
00067 
00068 inline void addObjToProc(ProcArray* parr, ObjGraph* ogr, std::vector<int>*
00069     pe_obj, int pe_index, int obj_index) {
00070 
00071   
00072   ogr->vertices[obj_index].setNewPe(pe_index);
00073 
00074   
00075   pe_obj[pe_index].push_back(obj_index);
00076 
00077   
00078   parr->procs[pe_index].totalLoad() += ogr->vertices[obj_index].getVertexLoad();
00079 }
00080 
00081 inline void removeObjFromProc(ProcArray* parr, ObjGraph* ogr, std::vector<int>*
00082     pe_obj, int pe_index, int arr_index) {
00083 
00084   
00085   parr->procs[pe_index].totalLoad() -=
00086       ogr->vertices[pe_obj[pe_index][arr_index]].getVertexLoad();
00087 
00088   
00089   pe_obj[pe_index].erase(pe_obj[pe_index].begin() + arr_index);
00090 }
00091 
00092 
00093 inline int getMax(ProcArray* parr, std::vector<int>& max_pe_heap) {
00094   int p_index = max_pe_heap.front();
00095   std::pop_heap(max_pe_heap.begin(), max_pe_heap.end(),
00096       RefineSwapLB::ProcLoadGreaterIndex(parr));
00097   max_pe_heap.pop_back();
00098   return p_index;
00099 }
00100 
00101 bool refine(ProcArray* parr, ObjGraph* ogr, std::vector<int>& max_pe_heap, 
00102     std::vector<int>& min_pe_heap, std::vector<int>* pe_obj, int max_pe,
00103     double avg_load, double threshold) {
00104 
00105   int best_p, best_p_iter, arr_index;
00106   bool allocated = false;
00107   int pe_considered;
00108   int obj_considered;
00109   double best_size = 0.0;
00110   std::sort(pe_obj[max_pe].begin(), pe_obj[max_pe].end(), RefineSwapLB::ObjLoadGreater(ogr));
00111 
00112   
00113   
00114 
00115   for (int i = (pe_obj[max_pe].size()-1); i >= 0; i--) {
00116     for (int j = 0; j < min_pe_heap.size(); j++) {
00117       obj_considered = pe_obj[max_pe][i];
00118       pe_considered = min_pe_heap[j];
00119 
00120       
00121       if (!ogr->vertices[obj_considered].isMigratable()) continue;
00122    
00123       if (parr->procs[pe_considered].getTotalLoad() +
00124           ogr->vertices[obj_considered].getVertexLoad() < (avg_load + threshold)) {
00125     
00126           best_size = ogr->vertices[obj_considered].getVertexLoad();
00127           best_p = pe_considered;
00128           best_p_iter = j;
00129           arr_index = i;
00130           allocated = true;
00131           break;
00132     
00133       }
00134     }
00135   }
00136 
00137   if (allocated) {
00138 
00139     int best_obj = pe_obj[max_pe][arr_index];
00140     addObjToProc(parr, ogr, pe_obj, best_p, best_obj);
00141     removeObjFromProc(parr, ogr, pe_obj, max_pe, arr_index);
00142 
00143     
00144     if (parr->procs[max_pe].getTotalLoad() > (avg_load + threshold)) {
00145       
00146       max_pe_heap.push_back(max_pe);
00147       std::push_heap(max_pe_heap.begin(), max_pe_heap.end(),
00148           RefineSwapLB::ProcLoadGreaterIndex(parr));
00149     } else if (parr->procs[max_pe].getTotalLoad() < (avg_load - threshold)) {
00150       
00151       min_pe_heap.push_back(max_pe);
00152     }
00153 
00154     if (parr->procs[best_p].getTotalLoad() > (avg_load - threshold)) {
00155       
00156       min_pe_heap.erase(min_pe_heap.begin() + best_p_iter);
00157     }
00158   }
00159   return allocated;
00160 }
00161 
00162 bool IsSwapPossWithPe(ProcArray* parr, ObjGraph* ogr, std::vector<int>* pe_obj,
00163     std::vector<int>& max_pe_heap, std::vector<int>& min_pe_heap,
00164     int max_pe, int pe_considered, int pe_cons_iter, double diff,
00165     double avg_load, double threshold) {
00166 
00167   bool set = false;
00168   for (int i = pe_obj[max_pe].size() - 1; i >= 0; i--) {
00169     for (int j = 0; j < pe_obj[pe_considered].size(); j++) {
00170       int pe_cons = pe_obj[pe_considered][j];
00171       int max_pe_obj = pe_obj[max_pe][i];
00172      
00173      
00174      
00175 
00176       if (ogr->vertices[pe_cons].getVertexLoad() <
00177           ogr->vertices[max_pe_obj].getVertexLoad() &&
00178           ogr->vertices[pe_cons].isMigratable() &&
00179           ogr->vertices[max_pe_obj].isMigratable()) {
00180         if ((diff + ogr->vertices[pe_cons].getVertexLoad()) >
00181             ogr->vertices[max_pe_obj].getVertexLoad()) {
00182           
00183           set = true;
00184 
00185           addObjToProc(parr, ogr, pe_obj, pe_considered, max_pe_obj);
00186           removeObjFromProc(parr, ogr, pe_obj, max_pe, i);
00187 
00188           addObjToProc(parr, ogr, pe_obj, max_pe, pe_cons);
00189           removeObjFromProc(parr, ogr, pe_obj, pe_considered, j);
00190 
00191           
00192           if (parr->procs[max_pe].getTotalLoad() > (avg_load + threshold)) {
00193             
00194             max_pe_heap.push_back(max_pe);
00195             std::push_heap(max_pe_heap.begin(), max_pe_heap.end(),
00196                 RefineSwapLB::ProcLoadGreaterIndex(parr));
00197           } else if (parr->procs[max_pe].getTotalLoad() < (avg_load - threshold)) {
00198             
00199             min_pe_heap.push_back(max_pe);
00200           }
00201 
00202           if (parr->procs[pe_considered].getTotalLoad() > (avg_load - threshold)) {
00203             
00204             min_pe_heap.erase(min_pe_heap.begin() + pe_cons_iter);
00205           }
00206           break;
00207         }
00208       }
00209     }
00210 
00211     if (set) {
00212       break;
00213     }
00214   }
00215   return set;
00216 }
00217 
00218 bool refineSwap(ProcArray* parr, ObjGraph* ogr, std::vector<int>& max_pe_heap, 
00219     std::vector<int>& min_pe_heap, std::vector<int>* pe_obj, int max_pe,
00220     double avg_load, double threshold) {
00221 
00222   double diff = 0;
00223   bool is_possible = false;
00224   int pe_considered;
00225   int pe_cons_iter;
00226   for (int i = 0; i < min_pe_heap.size(); i++) {
00227     pe_considered = min_pe_heap[i];
00228     pe_cons_iter = i;
00229     std::sort(pe_obj[pe_considered].begin(), pe_obj[pe_considered].end(), RefineSwapLB::ObjLoadGreater(ogr));
00230     diff = avg_load - parr->procs[pe_considered].getTotalLoad();
00231 
00232 
00233 
00234     is_possible = IsSwapPossWithPe(parr, ogr, pe_obj, max_pe_heap, min_pe_heap, max_pe,
00235         pe_considered, pe_cons_iter, diff, avg_load, threshold); 
00236     if (is_possible) {
00237       break;
00238     }
00239   }
00240 
00241   if (!is_possible) {
00242     return false;
00243   }
00244 
00245   return true;
00246 }
00247 
00248 void RefineSwapLB::work(LDStats* stats)
00249 {
00251   ProcArray *parr = new ProcArray(stats);       
00252   ObjGraph *ogr = new ObjGraph(stats);          
00253 
00254 
00257   if (_lb_args.debug()>1) 
00258     CkPrintf("[%d] In RefineSwapLB strategy\n",CkMyPe());
00259 
00260   int vert;
00261   double avg_load = parr->getAverageLoad();
00262   double threshold = avg_load * 0.01;
00263   double lower_bound_load = avg_load - threshold;
00264   double upper_bound_load = avg_load + threshold;
00265 
00266   if (_lb_args.debug()>1)
00267     cout <<"Average load " << avg_load << endl;
00268 
00269   std::vector<int> min_pe_heap;
00270   std::vector<int> max_pe_heap;
00271 
00272   std::vector<int>* pe_obj = new std::vector<int>[parr->procs.size()];
00273 
00274 
00275   
00276   for (int i = 0; i < ogr->vertices.size(); i++) {
00277     pe_obj[ogr->vertices[i].getCurrentPe()].push_back(i);
00278 
00279   }
00280 
00281   
00282   
00283   for (int i = 0; i < parr->procs.size(); i++) {
00284     
00285     if (parr->procs[i].getTotalLoad() > upper_bound_load) {
00286       max_pe_heap.push_back(i);
00287     } else if (parr->procs[i].getTotalLoad() < lower_bound_load) {
00288       min_pe_heap.push_back(i);
00289     }
00290   }
00291 
00292   std::make_heap(max_pe_heap.begin(), max_pe_heap.end(), RefineSwapLB::ProcLoadGreaterIndex(parr));
00293 
00294   while (max_pe_heap.size() != 0 && min_pe_heap.size() != 0) {
00295     int p_index = getMax(parr, max_pe_heap);
00296     ProcInfo &pinfo = parr->procs[p_index];
00297 
00298     bool success = refine(parr, ogr, max_pe_heap, min_pe_heap, pe_obj, p_index, avg_load, threshold);
00299     
00300 
00301     if (!success) {
00302       
00303 
00304       if (!refineSwap(parr, ogr, max_pe_heap, min_pe_heap, pe_obj, p_index, avg_load,
00305             threshold)) {
00306         max_pe_heap.push_back(p_index);
00307         std::push_heap(max_pe_heap.begin(), max_pe_heap.end(),
00308             RefineSwapLB::ProcLoadGreaterIndex(parr));
00309         break;
00310       }
00311     }
00312   }
00313 
00315   ogr->convertDecisions(stats);         
00316   delete[] pe_obj;
00317   delete parr;
00318   delete ogr;
00319 }
00320 
00321 #include "RefineSwapLB.def.h"
00322