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