00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "GridCommLB.decl.h"
00042
00043 #include "GridCommLB.h"
00044 #include "manager.h"
00045
00046 extern int quietModeRequested;
00047
00048 CreateLBFunc_Def (GridCommLB, "Grid communication load balancer (evenly distribute objects across each cluster)")
00049
00050
00051
00052
00053
00054
00055 GridCommLB::GridCommLB (const CkLBOptions &opt) : CBase_GridCommLB (opt)
00056 {
00057 char *value;
00058
00059
00060 lbname = (char *) "GridCommLB";
00061
00062 if (CkMyPe() == 0 && !quietModeRequested) {
00063 CkPrintf ("CharmLB> GridCommLB created.\n");
00064 }
00065
00066 if ((value = getenv ("CK_LDB_GRIDCOMMLB_MODE"))) {
00067 CK_LDB_GridCommLB_Mode = atoi (value);
00068 } else {
00069 CK_LDB_GridCommLB_Mode = CK_LDB_GRIDCOMMLB_MODE;
00070 }
00071
00072 if ((value = getenv ("CK_LDB_GRIDCOMMLB_BACKGROUND_LOAD"))) {
00073 CK_LDB_GridCommLB_Background_Load = atoi (value);
00074 } else {
00075 CK_LDB_GridCommLB_Background_Load = CK_LDB_GRIDCOMMLB_BACKGROUND_LOAD;
00076 }
00077
00078 if ((value = getenv ("CK_LDB_GRIDCOMMLB_LOAD_TOLERANCE"))) {
00079 CK_LDB_GridCommLB_Load_Tolerance = atof (value);
00080 } else {
00081 CK_LDB_GridCommLB_Load_Tolerance = CK_LDB_GRIDCOMMLB_LOAD_TOLERANCE;
00082 }
00083
00084 manager_init ();
00085 }
00086
00087
00088
00089
00090
00091
00092 GridCommLB::GridCommLB (CkMigrateMessage *msg) : CBase_GridCommLB (msg)
00093 {
00094 char *value;
00095
00096
00097 lbname = (char *) "GridCommLB";
00098
00099 if ((value = getenv ("CK_LDB_GRIDCOMMLB_MODE"))) {
00100 CK_LDB_GridCommLB_Mode = atoi (value);
00101 } else {
00102 CK_LDB_GridCommLB_Mode = CK_LDB_GRIDCOMMLB_MODE;
00103 }
00104
00105 if ((value = getenv ("CK_LDB_GRIDCOMMLB_BACKGROUND_LOAD"))) {
00106 CK_LDB_GridCommLB_Background_Load = atoi (value);
00107 } else {
00108 CK_LDB_GridCommLB_Background_Load = CK_LDB_GRIDCOMMLB_BACKGROUND_LOAD;
00109 }
00110
00111 if ((value = getenv ("CK_LDB_GRIDCOMMLB_LOAD_TOLERANCE"))) {
00112 CK_LDB_GridCommLB_Load_Tolerance = atof (value);
00113 } else {
00114 CK_LDB_GridCommLB_Load_Tolerance = CK_LDB_GRIDCOMMLB_LOAD_TOLERANCE;
00115 }
00116
00117 manager_init ();
00118 }
00119
00120
00121
00122
00123
00124
00125
00126 bool GridCommLB::QueryBalanceNow (int step)
00127 {
00128 if (_lb_args.debug() > 2) {
00129 CkPrintf ("[%d] GridCommLB is balancing on step %d.\n", CkMyPe(), step);
00130 }
00131
00132 return (true);
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 int GridCommLB::Get_Cluster (int pe)
00149 {
00150 return (0);
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 void GridCommLB::Initialize_PE_Data (CentralLB::LDStats *stats)
00165 {
00166 int min_speed;
00167 int i;
00168
00169
00170 PE_Data = new PE_Data_T[Num_PEs];
00171
00172 min_speed = MAXINT;
00173 for (i = 0; i < Num_PEs; i++) {
00174 (&PE_Data[i])->available = stats->procs[i].available;
00175 (&PE_Data[i])->cluster = Get_Cluster (i);
00176 (&PE_Data[i])->num_objs = 0;
00177 (&PE_Data[i])->num_lan_objs = 0;
00178 (&PE_Data[i])->num_lan_msgs = 0;
00179 (&PE_Data[i])->num_wan_objs = 0;
00180 (&PE_Data[i])->num_wan_msgs = 0;
00181 (&PE_Data[i])->relative_speed = 0.0;
00182 (&PE_Data[i])->scaled_load = 0.0;
00183
00184 if (stats->procs[i].pe_speed < min_speed) {
00185 min_speed = stats->procs[i].pe_speed;
00186 }
00187 }
00188
00189
00190
00191 for (i = 0; i < Num_PEs; i++) {
00192 (&PE_Data[i])->relative_speed = (double) (stats->procs[i].pe_speed / min_speed);
00193 if (CK_LDB_GridCommLB_Background_Load) {
00194 (&PE_Data[i])->scaled_load += stats->procs[i].bg_walltime;
00195 }
00196 }
00197 }
00198
00199
00200
00201
00202
00203
00204 int GridCommLB::Available_PE_Count ()
00205 {
00206 int available_pe_count;
00207 int i;
00208
00209
00210 available_pe_count = 0;
00211 for (i = 0; i < Num_PEs; i++) {
00212 if ((&PE_Data[i])->available) {
00213 available_pe_count += 1;
00214 }
00215 }
00216 return (available_pe_count);
00217 }
00218
00219
00220
00221
00222
00223
00224 int GridCommLB::Compute_Number_Of_Clusters ()
00225 {
00226 int max_cluster;
00227 int i;
00228
00229
00230 max_cluster = 0;
00231 for (i = 0; i < Num_PEs; i++) {
00232 if ((&PE_Data[i])->cluster < 0) {
00233 return (-1);
00234 }
00235
00236 if ((&PE_Data[i])->cluster > max_cluster) {
00237 max_cluster = (&PE_Data[i])->cluster;
00238 }
00239 }
00240 return (max_cluster + 1);
00241 }
00242
00243
00244
00245
00246
00247
00248 void GridCommLB::Initialize_Object_Data (CentralLB::LDStats *stats)
00249 {
00250 int i;
00251
00252
00253 Object_Data = new Object_Data_T[Num_Objects];
00254
00255 for (i = 0; i < Num_Objects; i++) {
00256 (&Object_Data[i])->migratable = (&stats->objData[i])->migratable;
00257 (&Object_Data[i])->cluster = Get_Cluster (stats->from_proc[i]);
00258 (&Object_Data[i])->from_pe = stats->from_proc[i];
00259 (&Object_Data[i])->to_pe = -1;
00260 (&Object_Data[i])->num_lan_msgs = 0;
00261 (&Object_Data[i])->num_wan_msgs = 0;
00262 (&Object_Data[i])->load = (&stats->objData[i])->wallTime;
00263 }
00264 }
00265
00266
00267
00268
00269
00270
00271 void GridCommLB::Examine_InterObject_Messages (CentralLB::LDStats *stats)
00272 {
00273 int i;
00274 int j;
00275 LDCommData *com_data;
00276 int send_object;
00277 int send_pe;
00278 int send_cluster;
00279 int recv_object;
00280 int recv_pe;
00281 int recv_cluster;
00282 const LDObjKey *recv_objects;
00283 int num_objects;
00284
00285
00286 for (i = 0; i < stats->n_comm; i++) {
00287 com_data = &(stats->commData[i]);
00288 if ((!com_data->from_proc()) && (com_data->recv_type() == LD_OBJ_MSG)) {
00289 send_object = stats->getHash (com_data->sender);
00290 recv_object = stats->getHash (com_data->receiver.get_destObj());
00291
00292 if ((send_object < 0) || (send_object > Num_Objects) || (recv_object < 0) || (recv_object > Num_Objects)) {
00293 continue;
00294 }
00295
00296 send_pe = (&Object_Data[send_object])->from_pe;
00297 recv_pe = (&Object_Data[recv_object])->from_pe;
00298
00299 send_cluster = Get_Cluster (send_pe);
00300 recv_cluster = Get_Cluster (recv_pe);
00301
00302 if (send_cluster == recv_cluster) {
00303 (&Object_Data[send_object])->num_lan_msgs += com_data->messages;
00304 } else {
00305 (&Object_Data[send_object])->num_wan_msgs += com_data->messages;
00306 }
00307 } else if (com_data->receiver.get_type() == LD_OBJLIST_MSG) {
00308 send_object = stats->getHash (com_data->sender);
00309
00310 if ((send_object < 0) || (send_object > Num_Objects)) {
00311 continue;
00312 }
00313
00314 send_pe = (&Object_Data[send_object])->from_pe;
00315 send_cluster = Get_Cluster (send_pe);
00316
00317 recv_objects = com_data->receiver.get_destObjs (num_objects);
00318
00319 for (j = 0; j < num_objects; j++) {
00320 recv_object = stats->getHash (recv_objects[j]);
00321
00322 if ((recv_object < 0) || (recv_object > Num_Objects)) {
00323 continue;
00324 }
00325
00326 recv_pe = (&Object_Data[recv_object])->from_pe;
00327 recv_cluster = Get_Cluster (recv_pe);
00328
00329 if (send_cluster == recv_cluster) {
00330 (&Object_Data[send_object])->num_lan_msgs += com_data->messages;
00331 } else {
00332 (&Object_Data[send_object])->num_wan_msgs += com_data->messages;
00333 }
00334 }
00335 }
00336 }
00337 }
00338
00339
00340
00341
00342
00343
00344 void GridCommLB::Map_NonMigratable_Objects_To_PEs ()
00345 {
00346 int i;
00347
00348
00349 for (i = 0; i < Num_Objects; i++) {
00350 if (!((&Object_Data[i])->migratable)) {
00351 if (_lb_args.debug() > 1) {
00352 CkPrintf ("[%d] GridCommLB identifies object %d as non-migratable.\n", CkMyPe(), i);
00353 }
00354
00355 Assign_Object_To_PE (i, (&Object_Data[i])->from_pe);
00356 }
00357 }
00358 }
00359
00360
00361
00362
00363
00364
00365 void GridCommLB::Map_Migratable_Objects_To_PEs (int cluster)
00366 {
00367 int target_object;
00368 int target_pe;
00369
00370
00371 while (1) {
00372 target_object = Find_Maximum_Object (cluster);
00373 target_pe = Find_Minimum_PE (cluster);
00374
00375 if ((target_object == -1) || (target_pe == -1)) {
00376 break;
00377 }
00378
00379 Assign_Object_To_PE (target_object, target_pe);
00380 }
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 int GridCommLB::Find_Maximum_Object (int cluster)
00394 {
00395 int max_index;
00396 int max_load_index;
00397 double max_load;
00398 int max_wan_msgs_index;
00399 int max_wan_msgs;
00400 double load_tolerance;
00401 int i;
00402
00403
00404 max_index = -1;
00405
00406 max_load_index = -1;
00407 max_load = -1.0;
00408
00409 max_wan_msgs_index = -1;
00410 max_wan_msgs = -1;
00411
00412 for (i = 0; i < Num_Objects; i++) {
00413 if (((&Object_Data[i])->cluster == cluster) && ((&Object_Data[i])->to_pe == -1)) {
00414 if ((&Object_Data[i])->load > max_load) {
00415 max_load_index = i;
00416 max_load = (&Object_Data[i])->load;
00417 }
00418 if ((&Object_Data[i])->num_wan_msgs > max_wan_msgs) {
00419 max_wan_msgs_index = i;
00420 max_wan_msgs = (&Object_Data[i])->num_wan_msgs;
00421 }
00422 }
00423 }
00424
00425 if (max_load_index < 0) {
00426 return (max_load_index);
00427 }
00428
00429 if ((&Object_Data[max_load_index])->num_wan_msgs >= (&Object_Data[max_wan_msgs_index])->num_wan_msgs) {
00430 return (max_load_index);
00431 }
00432
00433 load_tolerance = (&Object_Data[max_load_index])->load * CK_LDB_GridCommLB_Load_Tolerance;
00434
00435 max_index = max_load_index;
00436
00437 for (i = 0; i < Num_Objects; i++) {
00438 if (((&Object_Data[i])->cluster == cluster) && ((&Object_Data[i])->to_pe == -1)) {
00439 if (i != max_load_index) {
00440 if (fabs ((&Object_Data[max_load_index])->load - (&Object_Data[i])->load) <= load_tolerance) {
00441 if ((&Object_Data[i])->num_wan_msgs > (&Object_Data[max_index])->num_wan_msgs) {
00442 max_index = i;
00443 }
00444 }
00445 }
00446 }
00447 }
00448
00449 return (max_index);
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 int GridCommLB::Find_Minimum_PE (int cluster)
00469 {
00470 if (CK_LDB_GridCommLB_Mode == 0) {
00471 int min_index;
00472 int min_objs;
00473 int i;
00474
00475
00476 min_index = -1;
00477 min_objs = MAXINT;
00478
00479 for (i = 0; i < Num_PEs; i++) {
00480 if (((&PE_Data[i])->available) && ((&PE_Data[i])->cluster == cluster)) {
00481 if ((&PE_Data[i])->num_objs < min_objs) {
00482 min_index = i;
00483 min_objs = (&PE_Data[i])->num_objs;
00484 } else if (((&PE_Data[i])->num_objs == min_objs) &&
00485 ((&PE_Data[i])->num_wan_objs < (&PE_Data[min_index])->num_wan_objs)) {
00486 min_index = i;
00487 } else if (((&PE_Data[i])->num_objs == min_objs) &&
00488 ((&PE_Data[i])->num_wan_objs == (&PE_Data[min_index])->num_wan_objs) &&
00489 ((&PE_Data[i])->num_wan_msgs < (&PE_Data[min_index])->num_wan_msgs)) {
00490 min_index = i;
00491 } else if (((&PE_Data[i])->num_objs == min_objs) &&
00492 ((&PE_Data[i])->num_wan_objs == (&PE_Data[min_index])->num_wan_objs) &&
00493 ((&PE_Data[i])->num_wan_msgs == (&PE_Data[min_index])->num_wan_msgs) &&
00494 ((&PE_Data[i])->scaled_load < (&PE_Data[min_index])->scaled_load)) {
00495 min_index = i;
00496 }
00497 }
00498 }
00499
00500 return (min_index);
00501 } else if (CK_LDB_GridCommLB_Mode == 1) {
00502 int min_index;
00503 int min_load_index;
00504 double min_scaled_load;
00505 int min_wan_msgs_index;
00506 int min_wan_msgs;
00507 double load_tolerance;
00508 int i;
00509
00510
00511 min_index = -1;
00512
00513 min_load_index = -1;
00514 min_scaled_load = MAXDOUBLE;
00515
00516 min_wan_msgs_index = -1;
00517 min_wan_msgs = MAXINT;
00518
00519 for (i = 0; i < Num_PEs; i++) {
00520 if (((&PE_Data[i])->available) && ((&PE_Data[i])->cluster == cluster)) {
00521 if ((&PE_Data[i])->scaled_load < min_scaled_load) {
00522 min_load_index = i;
00523 min_scaled_load = (&PE_Data[i])->scaled_load;
00524 }
00525 if ((&PE_Data[i])->num_wan_msgs < min_wan_msgs) {
00526 min_wan_msgs_index = i;
00527 min_wan_msgs = (&PE_Data[i])->num_wan_msgs;
00528 }
00529 }
00530 }
00531
00532
00533 if (min_load_index < 0) {
00534 return (min_load_index);
00535 }
00536
00537
00538
00539
00540 if ((&PE_Data[min_load_index])->num_wan_msgs <= (&PE_Data[min_wan_msgs_index])->num_wan_msgs) {
00541 return (min_load_index);
00542 }
00543
00544
00545
00546
00547
00548 load_tolerance = (&PE_Data[min_load_index])->scaled_load * CK_LDB_GridCommLB_Load_Tolerance;
00549
00550 min_index = min_load_index;
00551
00552 for (i = 0; i < Num_PEs; i++) {
00553 if (((&PE_Data[i])->available) && ((&PE_Data[i])->cluster == cluster)) {
00554 if (i != min_load_index) {
00555 if (fabs ((&PE_Data[i])->scaled_load - (&PE_Data[min_load_index])->scaled_load) <= load_tolerance) {
00556 if ((&PE_Data[i])->num_wan_msgs < (&PE_Data[min_index])->num_wan_msgs) {
00557 min_index = i;
00558 }
00559 }
00560 }
00561 }
00562 }
00563
00564 return (min_index);
00565 } else {
00566 if (_lb_args.debug() > 0) {
00567 CkPrintf ("[%d] GridCommLB was told to use bad mode (%d).\n", CkMyPe(), CK_LDB_GridCommLB_Mode);
00568 }
00569 return (-1);
00570 }
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581 void GridCommLB::Assign_Object_To_PE (int target_object, int target_pe)
00582 {
00583 (&Object_Data[target_object])->to_pe = target_pe;
00584
00585 (&PE_Data[target_pe])->num_objs += 1;
00586
00587 if ((&Object_Data[target_object])->num_lan_msgs > 0) {
00588 (&PE_Data[target_pe])->num_lan_objs += 1;
00589 (&PE_Data[target_pe])->num_lan_msgs += (&Object_Data[target_object])->num_lan_msgs;
00590 }
00591
00592 if ((&Object_Data[target_object])->num_wan_msgs > 0) {
00593 (&PE_Data[target_pe])->num_wan_objs += 1;
00594 (&PE_Data[target_pe])->num_wan_msgs += (&Object_Data[target_object])->num_wan_msgs;
00595 }
00596
00597 (&PE_Data[target_pe])->scaled_load += (&Object_Data[target_object])->load / (&PE_Data[target_pe])->relative_speed;
00598 }
00599
00600
00601
00602
00603
00604
00605
00606 void GridCommLB::work (LDStats *stats)
00607 {
00608 int i;
00609
00610
00611 if (_lb_args.debug() > 0) {
00612 CkPrintf ("[%d] GridCommLB is working (mode=%d, background load=%d, load tolerance=%f).\n", CkMyPe(), CK_LDB_GridCommLB_Mode, CK_LDB_GridCommLB_Background_Load, CK_LDB_GridCommLB_Load_Tolerance);
00613 }
00614
00615
00616 stats->makeCommHash ();
00617
00618
00619 Num_PEs = stats->nprocs();
00620 Num_Objects = stats->n_objs;
00621
00622 if (_lb_args.debug() > 0) {
00623 CkPrintf ("[%d] GridCommLB is examining %d PEs and %d objects.\n", CkMyPe(), Num_PEs, Num_Objects);
00624 }
00625
00626
00627 Initialize_PE_Data (stats);
00628
00629
00630 if (Available_PE_Count() < 1) {
00631 if (_lb_args.debug() > 0) {
00632 CkPrintf ("[%d] GridCommLB finds no available PEs -- no balancing done.\n", CkMyPe());
00633 }
00634
00635 delete [] PE_Data;
00636
00637 return;
00638 }
00639
00640
00641
00642 Num_Clusters = Compute_Number_Of_Clusters ();
00643 if (Num_Clusters < 1) {
00644 if (_lb_args.debug() > 0) {
00645 CkPrintf ("[%d] GridCommLB finds incomplete PE cluster map -- no balancing done.\n", CkMyPe());
00646 }
00647
00648 delete [] PE_Data;
00649
00650 return;
00651 }
00652
00653 if (_lb_args.debug() > 0) {
00654 CkPrintf ("[%d] GridCommLB finds %d clusters.\n", CkMyPe(), Num_Clusters);
00655 }
00656
00657
00658 Initialize_Object_Data (stats);
00659
00660
00661 Examine_InterObject_Messages (stats);
00662
00663
00664 Map_NonMigratable_Objects_To_PEs ();
00665
00666
00667 for (i = 0; i < Num_Clusters; i++) {
00668 Map_Migratable_Objects_To_PEs (i);
00669 }
00670
00671
00672 for (i = 0; i < Num_Objects; i++) {
00673 stats->to_proc[i] = (&Object_Data[i])->to_pe;
00674
00675 if (_lb_args.debug() > 2) {
00676 CkPrintf ("[%d] GridCommLB migrates object %d from PE %d to PE %d.\n", CkMyPe(), i, stats->from_proc[i], stats->to_proc[i]);
00677 } else if (_lb_args.debug() > 1) {
00678 if (stats->to_proc[i] != stats->from_proc[i]) {
00679 CkPrintf ("[%d] GridCommLB migrates object %d from PE %d to PE %d.\n", CkMyPe(), i, stats->from_proc[i], stats->to_proc[i]);
00680 }
00681 }
00682 }
00683
00684
00685 delete [] Object_Data;
00686 delete [] PE_Data;
00687 }
00688
00689 #include "GridCommLB.def.h"