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