00001
00013
00014 #include "ScotchTopoLB.h"
00015 #include "TopoManager.h"
00016 #include "ckgraph.h"
00017 #include "scotch.h"
00018
00019 CreateLBFunc_Def(ScotchTopoLB, "Load balancing using the Scotch graph partitioning library")
00020
00021 ScotchTopoLB::ScotchTopoLB(const CkLBOptions &opt) : CentralLB(opt) {
00022 lbname = "ScotchTopoLB";
00023 if(CkMyPe() == 0)
00024 CkPrintf("ScotchTopoLB created\n");
00025 }
00026
00027 CmiBool ScotchTopoLB::QueryBalanceNow(int _step) {
00028 return CmiTrue;
00029 }
00030
00031 void ScotchTopoLB::work(LDStats *stats) {
00033 ProcArray *parr = new ProcArray(stats);
00034 ObjGraph *ogr = new ObjGraph(stats);
00035 TopoManager tmgr;
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(ogr->vertices[i].sendToList[j].getNumBytes() + 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_Arch arch;
00123 SCOTCH_Strat strat;
00124
00125
00126 SCOTCH_graphInit (&graph);
00127 SCOTCH_stratInit (&strat);
00128
00129 SCOTCH_graphBuild (&graph, baseval, vertnbr, verttab, NULL, velotab, NULL, edgenbr, edgetab, edlotab);
00130 SCOTCH_graphCheck (&graph);
00131
00132
00133 SCOTCH_stratGraphMapBuild (&strat, SCOTCH_STRATBALANCE, parr->procs.size (), 0.01);
00134
00135 SCOTCH_Num *pemap = (SCOTCH_Num *)malloc(sizeof(SCOTCH_Num) * vertnbr);
00136 SCOTCH_archInit (&arch);
00137 SCOTCH_archTorus3 (&arch, tmgr.getDimNX(), tmgr.getDimNY(), tmgr.getDimNZ());
00138
00139 SCOTCH_graphMap (&graph, &arch, &strat, pemap);
00140
00141 SCOTCH_graphExit (&graph);
00142 SCOTCH_archExit (&arch);
00143 SCOTCH_stratExit (&strat);
00144
00145 free(verttab);
00146 free(velotab);
00147 free(edgetab);
00148 free(edlotab);
00149 for(i = baseval; i < vertnbr; i++) {
00150 if(pemap[i] != ogr->vertices[i].getCurrentPe()) {
00151 ogr->vertices[i].setNewPe(pemap[i]);
00152 }
00153 }
00154
00155 free(pemap);
00157 ogr->convertDecisions(stats);
00158 delete ogr;
00159 }
00160
00161 #include "ScotchTopoLB.def.h"
00162