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