00001
00013
00014 #include "ScotchLB.h"
00015 #include "ckgraph.h"
00016 #include "scotch.h"
00017
00018 CreateLBFunc_Def(ScotchLB, "Load balancing using the Scotch graph partitioning library")
00019
00020 ScotchLB::ScotchLB(const CkLBOptions &opt) : CentralLB(opt) {
00021 lbname = "ScotchLB";
00022 if(CkMyPe() == 0)
00023 CkPrintf("ScotchLB created\n");
00024 }
00025
00026 CmiBool ScotchLB::QueryBalanceNow(int _step) {
00027 return CmiTrue;
00028 }
00029
00030 void ScotchLB::work(LDStats *stats) {
00032 ProcArray *parr = new ProcArray(stats);
00033 ObjGraph *ogr = new ObjGraph(stats);
00034 double start_time = CmiWallTimer();
00035
00037
00038 SCOTCH_Num baseval = 0;
00039 SCOTCH_Num vertnbr = ogr->vertices.size();
00040 SCOTCH_Num edgenbr = 0;
00041
00042 double maxLoad = 0.0;
00043 double minLoad = 0.0;
00044 if (vertnbr > 0) {
00045 minLoad = ogr->vertices[baseval].getVertexLoad();
00046 }
00047
00048 long maxBytes = 1;
00049 int i, j, k, vert;
00050
00051
00053 for(i = baseval; i < vertnbr; i++) {
00054 for(j = 0; j < ogr->vertices[i].sendToList.size(); j++) {
00055 vert = ogr->vertices[i].sendToList[j].getNeighborId();
00056 for(k = 0; k < ogr->vertices[i].recvFromList.size(); k++) {
00057 if(ogr->vertices[i].recvFromList[k].getNeighborId() == vert) {
00058 ogr->vertices[i].sendToList[j].setNumBytes(
00059 ogr->vertices[i].sendToList[j].getNumBytes() +
00060 ogr->vertices[i].recvFromList[k].getNumBytes());
00061 ogr->vertices[i].recvFromList.erase(ogr->vertices[i].recvFromList.begin() + k);
00062 }
00063 }
00064 }
00065 }
00067 for(i = baseval; i < vertnbr; i++) {
00068 if(ogr->vertices[i].getVertexLoad() > maxLoad)
00069 maxLoad = ogr->vertices[i].getVertexLoad();
00070
00071 if (ogr->vertices[i].getVertexLoad() < minLoad) {
00072 minLoad = ogr->vertices[i].getVertexLoad();
00073 }
00074 edgenbr += ogr->vertices[i].sendToList.size() + ogr->vertices[i].recvFromList.size();
00075 }
00076
00077 for(i = baseval; i < vertnbr; i++) {
00078 for(j = 0; j < ogr->vertices[i].sendToList.size(); j++) {
00079 if (ogr->vertices[i].sendToList[j].getNumBytes() > maxBytes) {
00080 maxBytes = ogr->vertices[i].sendToList[j].getNumBytes();
00081 }
00082 }
00083 for(j = 0; j < ogr->vertices[i].recvFromList.size(); j++) {
00084 if (ogr->vertices[i].recvFromList[j].getNumBytes() > maxBytes) {
00085 maxBytes = ogr->vertices[i].recvFromList[j].getNumBytes();
00086 }
00087 }
00088 }
00089
00090
00091
00092 SCOTCH_Num *verttab = (SCOTCH_Num *)malloc(sizeof(SCOTCH_Num) * (vertnbr+1));
00093
00094 SCOTCH_Num *velotab = (SCOTCH_Num *)malloc(sizeof(SCOTCH_Num) * vertnbr);
00095
00096 SCOTCH_Num *edgetab = (SCOTCH_Num *)malloc(sizeof(SCOTCH_Num) * edgenbr);
00097
00098 SCOTCH_Num *edlotab = (SCOTCH_Num *)malloc(sizeof(SCOTCH_Num) * edgenbr);
00099
00100 int edgeNum = 0;
00101 double ratio = 256.0/maxLoad;
00102 double byteRatio = 1024.0/maxBytes;
00103
00104 for(i = baseval; i < vertnbr; i++) {
00105 verttab[i] = edgeNum;
00106 velotab[i] = (SCOTCH_Num) ceil(ogr->vertices[i].getVertexLoad() * ratio);
00107 for(j = 0; j < ogr->vertices[i].sendToList.size(); j++) {
00108 edgetab[edgeNum] = ogr->vertices[i].sendToList[j].getNeighborId();
00109 edlotab[edgeNum] = (int) ceil(ogr->vertices[i].sendToList[j].getNumBytes() * byteRatio);
00110 edgeNum++;
00111 }
00112 for(j = 0; j < ogr->vertices[i].recvFromList.size(); j++) {
00113 edgetab[edgeNum] = ogr->vertices[i].recvFromList[j].getNeighborId();
00114 edlotab[edgeNum] = (int) ceil(ogr->vertices[i].recvFromList[j].getNumBytes() * byteRatio);
00115 edgeNum++;
00116 }
00117 }
00118 verttab[i] = edgeNum;
00119 CkAssert(edgeNum == edgenbr);
00120
00121 SCOTCH_Graph graph;
00122 SCOTCH_Strat strat;
00123
00124
00125 SCOTCH_graphInit (&graph);
00126 SCOTCH_stratInit (&strat);
00127
00128 SCOTCH_graphBuild (&graph, baseval, vertnbr, verttab, NULL, velotab, NULL, edgenbr, edgetab, edlotab);
00129 SCOTCH_graphCheck (&graph);
00130
00131 SCOTCH_stratGraphMapBuild (&strat, SCOTCH_STRATBALANCE, parr->procs.size (), 0.01);
00132 SCOTCH_Num *pemap = (SCOTCH_Num *)malloc(sizeof(SCOTCH_Num) * vertnbr);
00133
00134 SCOTCH_graphPart(&graph, parr->procs.size(), &strat, pemap);
00135
00136
00137 SCOTCH_graphExit (&graph);
00138 SCOTCH_stratExit (&strat);
00139
00140 free(verttab);
00141 free(velotab);
00142 free(edgetab);
00143 free(edlotab);
00144 for(i = baseval; i < vertnbr; i++) {
00145 if(pemap[i] != ogr->vertices[i].getCurrentPe()) {
00146 ogr->vertices[i].setNewPe(pemap[i]);
00147 }
00148 }
00149
00150 free(pemap);
00152 ogr->convertDecisions(stats);
00153 delete parr;
00154 delete ogr;
00155 }
00156
00157 #include "ScotchLB.def.h"
00158