00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <parmetislib.h>
00015
00016 #define PackWeightWhereInfo(a, b) (((a)<<10) + (b))
00017 #define SelectWhere(a) ((a)%1024)
00018 #define SelectWeight(a) (((a)>>10))
00019
00020
00021
00022
00023
00024
00025 void ComputeNodePartitionParams(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace)
00026 {
00027 int i, j, nparts, nvtxs, nsep, firstvtx, lastvtx;
00028 idxtype *xadj, *ladjncy, *adjwgt, *vtxdist, *vwgt, *lpwgts, *gpwgts, *sepind;
00029 idxtype *where, *swhere, *rwhere;
00030 NRInfoType *rinfo, *myrinfo;
00031 int me, other, otherwgt;
00032
00033 IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->KWayInitTmr));
00034
00035 nvtxs = graph->nvtxs;
00036 nparts = ctrl->nparts;
00037
00038 vtxdist = graph->vtxdist;
00039 xadj = graph->xadj;
00040 ladjncy = graph->adjncy;
00041 adjwgt = graph->adjwgt;
00042 vwgt = graph->vwgt;
00043
00044 where = graph->where;
00045 rinfo = graph->nrinfo = (NRInfoType *)GKmalloc(sizeof(NRInfoType)*nvtxs, "ComputeNodePartitionParams: rinfo");
00046 lpwgts = graph->lpwgts = idxsmalloc(2*nparts, 0, "ComputePartitionParams: lpwgts");
00047 gpwgts = graph->gpwgts = idxmalloc(2*nparts, "ComputePartitionParams: gpwgts");
00048 sepind = graph->sepind = idxmalloc(nvtxs, "ComputePartitionParams: sepind");
00049
00050 firstvtx = vtxdist[ctrl->mype];
00051 lastvtx = vtxdist[ctrl->mype+1];
00052
00053
00054
00055
00056
00057
00058 swhere = wspace->indices;
00059 rwhere = where + nvtxs;
00060
00061 for (i=0; i<nvtxs; i++) {
00062 ASSERTP(ctrl, where[i] >= 0 && where[i] < 2*nparts, (ctrl, "%d\n", where[i]) );
00063 where[i] = PackWeightWhereInfo(vwgt[i], where[i]);
00064 }
00065
00066 CommInterfaceData(ctrl, graph, where, swhere, rwhere);
00067
00068
00069
00070
00071 for (nsep=i=0; i<nvtxs; i++) {
00072 me = SelectWhere(where[i]);
00073 ASSERT(ctrl, me >= 0 && me < 2*nparts);
00074 lpwgts[me] += vwgt[i];
00075
00076 if (me >= nparts) {
00077 sepind[nsep++] = i;
00078 lpwgts[2*nparts-1] += vwgt[i];
00079
00080 myrinfo = rinfo+i;
00081 myrinfo->edegrees[0] = myrinfo->edegrees[1] = 0;
00082
00083 for (j=xadj[i]; j<xadj[i+1]; j++) {
00084 other = SelectWhere(where[ladjncy[j]]);
00085 otherwgt = SelectWeight(where[ladjncy[j]]);
00086 if (me != other)
00087 myrinfo->edegrees[other%2] += otherwgt;
00088 }
00089 }
00090 }
00091 graph->nsep = nsep;
00092
00093
00094 MPI_Allreduce((void *)lpwgts, (void *)gpwgts, 2*nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm);
00095 graph->mincut = gpwgts[2*nparts-1];
00096
00097 #ifdef XX
00098
00099 if (ctrl->mype == 0) {
00100 for (i=0; i<nparts; i+=2)
00101 printf("[%5d %5d %5d] ", gpwgts[i], gpwgts[i+1], gpwgts[nparts+i]);
00102 printf("\n");
00103 }
00104 #endif
00105
00106 IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->KWayInitTmr));
00107 }
00108
00109
00110
00111
00112
00113
00114 void KWayNodeRefine(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace, int npasses, floattype ubfraction)
00115 {
00116 int i, ii, j, k, pass, nvtxs, firstvtx, lastvtx, otherlastvtx, c, nmoves,
00117 nlupd, nsupd, nnbrs, nchanged, nsep;
00118 int npes = ctrl->npes, mype = ctrl->mype, nparts = ctrl->nparts;
00119 idxtype *xadj, *ladjncy, *adjwgt, *vtxdist, *vwgt;
00120 idxtype *where, *lpwgts, *gpwgts, *sepind;
00121 idxtype *peind, *recvptr, *sendptr;
00122 idxtype *update, *supdate, *rupdate, *pe_updates, *htable, *changed;
00123 idxtype *badminpwgt, *badmaxpwgt;
00124 KeyValueType *swchanges, *rwchanges;
00125 int *nupds_pe;
00126 NRInfoType *rinfo, *myrinfo;
00127 int from, me, other, otherwgt, oldcut;
00128
00129 IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->KWayTmr));
00130
00131 nvtxs = graph->nvtxs;
00132
00133 vtxdist = graph->vtxdist;
00134 xadj = graph->xadj;
00135 ladjncy = graph->adjncy;
00136 adjwgt = graph->adjwgt;
00137 vwgt = graph->vwgt;
00138
00139 firstvtx = vtxdist[mype];
00140 lastvtx = vtxdist[mype+1];
00141
00142 where = graph->where;
00143 rinfo = graph->nrinfo;
00144 lpwgts = graph->lpwgts;
00145 gpwgts = graph->gpwgts;
00146
00147 nsep = graph->nsep;
00148 sepind = graph->sepind;
00149
00150 nnbrs = graph->nnbrs;
00151 peind = graph->peind;
00152 recvptr = graph->recvptr;
00153 sendptr = graph->sendptr;
00154
00155 changed = idxmalloc(nvtxs, "KWayRefine: changed");
00156 rwchanges = wspace->pairs;
00157 swchanges = rwchanges + recvptr[nnbrs];
00158
00159 update = idxmalloc(nvtxs, "KWayRefine: update");
00160 supdate = wspace->indices;
00161 rupdate = supdate + recvptr[nnbrs];
00162 nupds_pe = imalloc(npes, "KWayRefine: nupds_pe");
00163
00164 htable = idxsmalloc(nvtxs+graph->nrecv, 0, "KWayRefine: lhtable");
00165
00166 badminpwgt = wspace->pv1;
00167 badmaxpwgt = wspace->pv2;
00168
00169 for (i=0; i<nparts; i+=2) {
00170 badminpwgt[i] = badminpwgt[i+1] = (1.0/ubfraction)*(gpwgts[i]+gpwgts[i+1])/2;
00171 badmaxpwgt[i] = badmaxpwgt[i+1] = ubfraction*(gpwgts[i]+gpwgts[i+1])/2;
00172 }
00173
00174 IFSET(ctrl->dbglvl, DBG_REFINEINFO, PrintNodeBalanceInfo(ctrl, nparts, gpwgts, badminpwgt, badmaxpwgt, 1));
00175
00176 for (pass=0; pass<npasses; pass++) {
00177 oldcut = graph->mincut;
00178
00179 for (c=0; c<2; c++) {
00180 for (i=0; i<nparts; i+=2) {
00181 badminpwgt[i] = badminpwgt[i+1] = (1.0/ubfraction)*(gpwgts[i]+gpwgts[i+1])/2;
00182 badmaxpwgt[i] = badmaxpwgt[i+1] = ubfraction*(gpwgts[i]+gpwgts[i+1])/2;
00183 }
00184
00185 nlupd = nsupd = nmoves = nchanged = 0;
00186 for (ii=0; ii<nsep; ii++) {
00187 i = sepind[ii];
00188 from = SelectWhere(where[i]);
00189
00190 ASSERT(ctrl, from >= nparts);
00191
00192
00193 if (rinfo[i].edegrees[(c+1)%2] <= vwgt[i]) {
00194 other = from%nparts+c;
00195
00196 if (gpwgts[other]+vwgt[i] > badmaxpwgt[other]) {
00197
00198 continue;
00199 }
00200
00201
00202 where[i] = PackWeightWhereInfo(vwgt[i], other);
00203
00204
00205 sepind[ii--] = sepind[--nsep];
00206
00207
00208
00209 lpwgts[from] -= vwgt[i];
00210 lpwgts[2*nparts-1] -= vwgt[i];
00211 lpwgts[other] += vwgt[i];
00212 gpwgts[other] += vwgt[i];
00213
00214
00215
00216
00217
00218 for (j=xadj[i]; j<xadj[i+1]; j++) {
00219 k = ladjncy[j];
00220 if (htable[k] == 0 && SelectWhere(where[k]) != other) {
00221 htable[k] = 1;
00222 if (k<nvtxs)
00223 update[nlupd++] = k;
00224 else
00225 supdate[nsupd++] = k;
00226 }
00227 }
00228 nmoves++;
00229 if (graph->pexadj[i+1]-graph->pexadj[i] > 0)
00230 changed[nchanged++] = i;
00231 }
00232 }
00233
00234
00235
00236
00237 CommChangedInterfaceData(ctrl, graph, nchanged, changed, where, swchanges, rwchanges, wspace->pv4);
00238
00239
00240 IFSET(ctrl->dbglvl, DBG_RMOVEINFO, rprintf(ctrl, "\t[%d %d], [%d %d %d]\n",
00241 pass, c, GlobalSESum(ctrl, nmoves), GlobalSESum(ctrl, nsupd), GlobalSESum(ctrl, nlupd)));
00242
00243
00244
00245
00246
00247
00248
00249 for (i=0; i<nnbrs; i++) {
00250 MPI_Irecv((void *)(rupdate+sendptr[i]), sendptr[i+1]-sendptr[i], IDX_DATATYPE,
00251 peind[i], 1, ctrl->comm, ctrl->rreq+i);
00252 }
00253
00254
00255 for (i=0; i<nsupd; i++) {
00256 htable[supdate[i]] = 0;
00257 supdate[i] = graph->imap[supdate[i]];
00258 }
00259 iidxsort(nsupd, supdate);
00260
00261 for (j=i=0; i<nnbrs; i++) {
00262 otherlastvtx = vtxdist[peind[i]+1];
00263 for (k=j; k<nsupd && supdate[k] < otherlastvtx; k++);
00264 MPI_Isend((void *)(supdate+j), k-j, IDX_DATATYPE, peind[i], 1, ctrl->comm, ctrl->sreq+i);
00265 j = k;
00266 }
00267
00268
00269 MPI_Waitall(nnbrs, ctrl->rreq, ctrl->statuses);
00270 for (i=0; i<nnbrs; i++)
00271 MPI_Get_count(ctrl->statuses+i, IDX_DATATYPE, nupds_pe+i);
00272 MPI_Waitall(nnbrs, ctrl->sreq, ctrl->statuses);
00273
00274
00275
00276
00277
00278 for (i=0; i<nnbrs; i++) {
00279 pe_updates = rupdate+sendptr[i];
00280 for (j=0; j<nupds_pe[i]; j++) {
00281 k = pe_updates[j];
00282 if (htable[k-firstvtx] == 0) {
00283 htable[k-firstvtx] = 1;
00284 update[nlupd++] = k-firstvtx;
00285 }
00286 }
00287 }
00288
00289
00290
00291
00292
00293
00294 nchanged = 0;
00295 for (ii=0; ii<nlupd; ii++) {
00296 i = update[ii];
00297 me = SelectWhere(where[i]);
00298 if (me < nparts && me%2 == (c+1)%2) {
00299 lpwgts[me] -= vwgt[i];
00300 where[i] = PackWeightWhereInfo(vwgt[i], nparts+me-(me%2));
00301 sepind[nsep++] = i;
00302 if (graph->pexadj[i+1]-graph->pexadj[i] > 0)
00303 changed[nchanged++] = i;
00304
00305 lpwgts[SelectWhere(where[i])] += vwgt[i];
00306 lpwgts[2*nparts-1] += vwgt[i];
00307
00308 }
00309 }
00310
00311
00312 CommChangedInterfaceData(ctrl, graph, nchanged, changed, where, swchanges, rwchanges, wspace->pv4);
00313
00314
00315
00316
00317
00318 for (ii=0; ii<nlupd; ii++) {
00319 i = update[ii];
00320 ASSERT(ctrl, htable[i] == 1);
00321
00322 htable[i] = 0;
00323
00324 me = SelectWhere(where[i]);
00325 if (me >= nparts) {
00326
00327
00328 myrinfo = rinfo+i;
00329 myrinfo->edegrees[0] = myrinfo->edegrees[1] = 0;
00330
00331 for (j=xadj[i]; j<xadj[i+1]; j++) {
00332 other = SelectWhere(where[ladjncy[j]]);
00333 otherwgt = SelectWeight(where[ladjncy[j]]);
00334 if (me != other)
00335 myrinfo->edegrees[other%2] += otherwgt;
00336 }
00337 }
00338 }
00339
00340
00341 MPI_Allreduce((void *)lpwgts, (void *)gpwgts, 2*nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm);
00342 graph->mincut = gpwgts[2*nparts-1];
00343
00344 IFSET(ctrl->dbglvl, DBG_REFINEINFO, PrintNodeBalanceInfo(ctrl, nparts, gpwgts, badminpwgt, badmaxpwgt, 0));
00345 }
00346
00347 if (graph->mincut == oldcut)
00348 break;
00349 }
00350
00351
00352 for (i=0; i<nvtxs+graph->nrecv; i++)
00353 where[i] = SelectWhere(where[i]);
00354
00355 GKfree((void **)&update, (void **)&nupds_pe, (void **)&htable, (void **)&changed, LTERM);
00356
00357 IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->KWayTmr));
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367 void PrintNodeBalanceInfo(CtrlType *ctrl, int nparts, idxtype *gpwgts, idxtype *badminpwgt, idxtype *badmaxpwgt, int title)
00368 {
00369 int i;
00370
00371 if (ctrl->mype == 0) {
00372 if (title)
00373 printf("K-way sep-refinement: TotalSep: %d, ", gpwgts[2*nparts-1]);
00374 else
00375 printf("\tTotalSep: %d, ", gpwgts[2*nparts-1]);
00376
00377 for (i=0; i<nparts; i+=2)
00378 printf(" [%5d %5d %5d %5d %5d]", gpwgts[i], gpwgts[i+1], gpwgts[nparts+i], badminpwgt[i], badmaxpwgt[i]);
00379 printf("\n");
00380 }
00381 MPI_Barrier(ctrl->comm);
00382 }
00383