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