00001
00005
00006
00007
00008
00009
00010
00011
00012 #include <LBSimulation.h>
00013 #include "GreedyAgentLB.h"
00014
00015 #define LOAD_OFFSET 0.05
00016
00017 extern int quietModeRequested;
00018
00019 CreateLBFunc_Def(GreedyAgentLB,"always assign the heaviest obj onto lightest loaded processor taking into account the topology")
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "GreedyAgentLB.def.h"
00029
00030 GreedyAgentLB::GreedyAgentLB(const CkLBOptions &opt): CBase_GreedyAgentLB(opt)
00031 {
00032 lbname = "GreedyAgentLB";
00033 if (CkMyPe()==0 && !quietModeRequested)
00034 CkPrintf("CharmLB> GreedyAgentLB created.\n");
00035 }
00036
00037 bool GreedyAgentLB::QueryBalanceNow(int _step)
00038 {
00039
00040 return true;
00041 }
00042
00043 bool GreedyAgentLB::Compare(double x, double y, HeapCmp cmp)
00044 {
00045 const int test = ((cmp == GT) ? (x > y) : (x < y));
00046
00047 if (test) return true;
00048 else return false;
00049 }
00050
00051
00052 void GreedyAgentLB::Heapify(HeapData *heap, int node, int heapSize, HeapCmp cmp)
00053 {
00054 int left = 2*node+1;
00055 int right = 2*node+2;
00056 int xchange;
00057
00058
00059 if (left <= heapSize && Compare(heap[left].load, heap[node].load, cmp))
00060 xchange = left;
00061 else xchange = node;
00062
00063 if (right <= heapSize && Compare(heap[right].load, heap[xchange].load, cmp))
00064 xchange = right;
00065
00066 if (xchange != node) {
00067 HeapData obj;
00068 obj = heap[node];
00069 heap[node] = heap[xchange];
00070 heap[xchange] = obj;
00071 Heapify(heap, xchange, heapSize, cmp);
00072 }
00073 }
00074
00075 void GreedyAgentLB::BuildHeap(HeapData *data, int heapSize, HeapCmp cmp)
00076 {
00077 int i;
00078 for(i=heapSize/2; i >= 0; i--)
00079 Heapify(data, i, heapSize, cmp);
00080 }
00081
00082 void GreedyAgentLB::HeapSort(HeapData *data, int heapSize, HeapCmp cmp)
00083 {
00084 int i;
00085 HeapData key;
00086
00087 int origSize = heapSize;
00088 BuildHeap(data, heapSize, cmp);
00089 for (i=heapSize; i > 0; i--) {
00090 key = data[0];
00091 data[0] = data[i];
00092 data[i] = key;
00093 heapSize--;
00094 Heapify(data, 0, heapSize, cmp);
00095 }
00096
00097 for (i=0; i<(origSize+1)/2; i++) {
00098 key = data[i];
00099 data[i] = data[origSize-i];
00100 data[origSize-i] = key;
00101 }
00102 }
00103
00104 GreedyAgentLB::HeapData*
00105 GreedyAgentLB::BuildObjectArray(CentralLB::LDStats* stats,
00106 int count, int *objCount)
00107 {
00108 HeapData *objData;
00109 int obj;
00110
00111
00112
00113
00114 objData = new HeapData[stats->n_objs];
00115 *objCount = 0;
00116 for(obj=0; obj < stats->n_objs; obj++) {
00117 LDObjData &oData = stats->objData[obj];
00118 int pe = stats->from_proc[obj];
00119 if (!oData.migratable) {
00120 if (!stats->procs[pe].available)
00121 CmiAbort("GreedyAgentLB cannot handle nonmigratable object on an unavial processor!\n");
00122 continue;
00123 }
00124 objData[*objCount].load = oData.wallTime * stats->procs[pe].pe_speed;
00125 objData[*objCount].pe = pe;
00126 objData[*objCount].id = obj;
00127 (*objCount)++;
00128 }
00129
00130 HeapSort(objData, *objCount-1, GT);
00131
00132
00133
00134
00135
00136 return objData;
00137 }
00138
00139 GreedyAgentLB::HeapData*
00140 GreedyAgentLB::BuildCpuArray(CentralLB::LDStats* stats,
00141 int count, int *peCount)
00142 {
00143 int pe;
00144
00145 *peCount = 0;
00146 for (pe = 0; pe < count; pe++)
00147 if (stats->procs[pe].available) (*peCount)++;
00148 HeapData *data = new HeapData[*peCount];
00149 int *map = new int[count];
00150
00151 *peCount = 0;
00152 for (pe=0; pe < count; pe++) {
00153 CentralLB::ProcStats &peData = stats->procs[pe];
00154
00155 data[*peCount].load = 0.0;
00156 map[pe] = -1;
00157 if (peData.available)
00158 {
00159 data[*peCount].load += peData.bg_walltime;
00160 data[*peCount].pe = data[*peCount].id = pe;
00161 map[pe] = *peCount;
00162 (*peCount)++;
00163 }
00164 }
00165
00166
00167 for (int obj = 0; obj < stats->n_objs; obj++)
00168 {
00169 LDObjData &oData = stats->objData[obj];
00170 if (!oData.migratable) {
00171 int pe = stats->from_proc[obj];
00172 pe = map[pe];
00173 if (pe==-1)
00174 CmiAbort("GreedyAgentLB: nonmigratable object on an unavail processor!\n");
00175 data[pe].load += oData.wallTime;
00176 }
00177 }
00178
00179
00180 for (pe = 0; pe<*peCount; pe++)
00181 data[pe].load *= stats->procs[data[pe].pe].pe_speed;
00182
00183 BuildHeap(data, *peCount-1, LT);
00184 delete [] map;
00185 return data;
00186 }
00187
00188 void GreedyAgentLB::work(LDStats* stats)
00189 {
00190 int i, obj, heapSize, objCount;
00191 int n_pes = stats->nprocs();
00192
00193 int *pemap = new int [n_pes];
00194 HeapData *cpuData = BuildCpuArray(stats, n_pes, &heapSize);
00195 HeapData *objData = BuildObjectArray(stats, n_pes, &objCount);
00196
00197 int max_neighbors=0;
00198
00199
00200
00201
00202
00203 CkPrintf("num procs in stats:%d\n", n_pes);
00204 topologyAgent = new TopologyAgent(stats, n_pes);
00205
00206 max_neighbors = topologyAgent->topo->max_neighbors();
00207
00208 if (_lb_args.debug()) CkPrintf("In GreedyAgentLB strategy\n",CkMyPe());
00209
00210 heapSize--;
00211
00212 HeapData *minCpu = new HeapData[n_pes];
00213 double minLoad = 0.0;
00214 double loadThreshold = 0.0;
00215 int *trialpes = new int[n_pes + 1];
00216 int *trialmap = new int[n_pes];
00217 int *existing_map = new int[objCount];
00218 Agent::Elem *preferList;
00219
00220 for(i=0;i<objCount;i++)
00221 existing_map[i]=-1;
00222
00223 int extractIndex=0;
00224
00225
00226
00227 CkPrintf("before assigning objects...objcount:%d\n",objCount);
00228 for (obj=0; obj < objCount; obj++) {
00229
00230
00231
00232
00233
00234 CkPrintf("obj count:%d\n",obj);
00235 for(i = 0; i <= n_pes; i++)
00236 trialpes[i]=-1;
00237
00238 if(extractIndex==0)
00239 minLoad = cpuData[0].load;
00240 else
00241 minLoad = minCpu[0].load;
00242
00243
00244
00245
00246 loadThreshold = minLoad*(1+LOAD_OFFSET);
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 while(1){
00259 if(cpuData[0].load > loadThreshold)
00260 break;
00261 minCpu[extractIndex]=cpuData[0];
00262 extractIndex++;
00263 cpuData[0]=cpuData[heapSize];
00264 heapSize--;
00265 if(heapSize==-1)
00266 break;
00267 Heapify(cpuData, 0, heapSize, LT);
00268 }
00269
00270
00271 int trialLen = 0;
00272 if(obj!=0){
00273 trialLen = max_neighbors*max_neighbors;
00274 if(trialLen > extractIndex)
00275 trialLen = extractIndex;
00276 }
00277 else
00278 trialLen = extractIndex;
00279
00280 for(i=0;i<trialLen;i++){
00281 trialpes[i]=minCpu[i].pe;
00282 trialmap[minCpu[i].pe]=i;
00283 }
00284 preferList = topologyAgent->my_preferred_procs(existing_map,objData[obj].id,trialpes,1);
00285
00286
00287
00288
00289 int minIndex = trialmap[preferList[0].pe];
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 const int dest = minCpu[minIndex].pe;
00303 const int id = objData[obj].id;
00304
00305
00306 minCpu[minIndex].load += objData[obj].load;
00307
00308 existing_map[id]=minCpu[minIndex].pe;
00309
00310
00311
00312 const int pe = objData[obj].pe;
00313
00314 if (dest != pe) {
00315 stats->to_proc[id] = dest;
00316 if (_lb_args.debug()>1)
00317 CkPrintf("[%d] Obj %d migrating from %d to %d\n", CkMyPe(),obj,pe,dest);
00318 }
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 heapSize++;
00334 extractIndex--;
00335 int location = heapSize;
00336 while (location>0 && cpuData[(location-1)/2].load > minCpu[minIndex].load) {
00337 cpuData[location] = cpuData[(location-1)/2];
00338 location = (location-1)/2;
00339 }
00340 cpuData[location] = minCpu[minIndex];
00341
00342 for(int r=minIndex;r<extractIndex;r++)
00343 minCpu[r] = minCpu[r+1];
00344 }
00345
00346 delete [] cpuData;
00347 delete [] objData;
00348 delete [] minCpu;
00349 }
00350
00351
00352