/* * Copyright 1997, Regents of the University of Minnesota * * xyzpart.c * * This file contains code that implements a coordinate based partitioning * * Started 7/11/97 * George * * $Id: xyzpart.c,v 1.3 2003/07/30 18:37:59 karypis Exp $ * */ #include /************************************************************************* * This function implements a simple coordinate based partitioning **************************************************************************/ void Coordinate_Partition(CtrlType *ctrl, GraphType *graph, int ndims, float *xyz, int setup, WorkSpaceType *wspace) { int i, j, k, nvtxs, firstvtx, icoord, coords[3]; idxtype *vtxdist; float max[3], min[3], gmin[3], gmax[3], shift[3], scale[3]; KeyValueType *cand; if (setup) SetUp(ctrl, graph, wspace); else graph->nrecv = 0; nvtxs = graph->nvtxs; vtxdist = graph->vtxdist; firstvtx = vtxdist[ctrl->mype]; cand = (KeyValueType *)GKmalloc(nvtxs*sizeof(KeyValueType), "Coordinate_Partition: cand"); /* Compute parameters for coordinate transformation */ for (k=0; k max[k]) max[k] = xyz[i*ndims+k]; } } /* Compute global min and max */ MPI_Allreduce((void *)min, (void *)gmin, ndims, MPI_FLOAT, MPI_MIN, ctrl->comm); MPI_Allreduce((void *)max, (void *)gmax, ndims, MPI_FLOAT, MPI_MAX, ctrl->comm); /* myprintf(ctrl, "Coordinate Range: %e %e, Global %e %e\n", min[0], max[0], gmin[0], gmax[0]); */ for (k=0; kxyztype) { case XYZ_XCOORD: for (i=0; i=0 && cand[i].key<=1000000); cand[i].val = firstvtx+i; } break; case XYZ_SPFILL: for (i=0; i=0; j--) { for (k=0; knpes, mype=ctrl->mype, firstvtx, lastvtx; idxtype *scounts, *rcounts, *vtxdist, *perm; KeyValueType *relmnts, *mypicks, *allpicks; nvtxs = graph->nvtxs; vtxdist = graph->vtxdist; scounts = wspace->pv1; rcounts = wspace->pv2; /* Allocate memory for the splitters */ mypicks = (KeyValueType *)GKmalloc(sizeof(KeyValueType)*(npes+1), "ParSort: mypicks"); allpicks = (KeyValueType *)GKmalloc(sizeof(KeyValueType)*npes*npes, "ParSort: allpicks"); /* Sort the local elements */ ikeysort(nvtxs, elmnts); /* Select the local npes-1 equally spaced elements */ for (i=1; icomm); /* PrintPairs(ctrl, npes*(npes-1), allpicks, "Allpicks"); */ /* Sort all the picks */ ikeyvalsort(npes*(npes-1), allpicks); /* PrintPairs(ctrl, npes*(npes-1), allpicks, "Allpicks"); */ /* Select the final splitters. Set the boundaries to simplify coding */ for (i=1; icomm); /* PrintVector(ctrl, npes, 0, scounts, "Scounts"); PrintVector(ctrl, npes, 0, rcounts, "Rcounts"); */ /* Allocate memory for sorted elements and receive them */ MAKECSR(i, npes, scounts); MAKECSR(i, npes, rcounts); nrecv = rcounts[npes]; if (wspace->nlarge >= nrecv) relmnts = (KeyValueType *)wspace->pairs; else relmnts = (KeyValueType *)GKmalloc(sizeof(KeyValueType)*nrecv, "ParSort: relmnts"); /* Issue the receives first */ for (i=0; icomm, ctrl->rreq+i); /* Issue the sends next */ for (i=0; icomm, ctrl->sreq+i); MPI_Waitall(npes, ctrl->rreq, ctrl->statuses); MPI_Waitall(npes, ctrl->sreq, ctrl->statuses); /* OK, now do the local sort of the relmnts. Use perm to keep track original order */ perm = idxmalloc(nrecv, "ParSort: perm"); for (i=0; icomm); firstvtx = lastvtx-nrecv; /*myprintf(ctrl, "first, last: %d %d\n", firstvtx, lastvtx); */ for (j=0, i=0; i firstvtx) { /* Found the first PE that is passed me */ if (vtxdist[i+1] >= lastvtx) { /* myprintf(ctrl, "Shifting %d elements to processor %d\n", lastvtx-firstvtx, i); */ for (k=0; k= lastvtx) break; } /* Reverse the ordering on the relmnts[].val */ for (i=0; i=0 && relmnts[i].keycomm, ctrl->rreq+i); /* Issue the sends next */ for (i=0; icomm, ctrl->sreq+i); MPI_Waitall(npes, ctrl->rreq, ctrl->statuses); MPI_Waitall(npes, ctrl->sreq, ctrl->statuses); /* Construct a partition for the graph */ graph->where = idxmalloc(graph->nvtxs+graph->nrecv, "PartSort: graph->where"); firstvtx = vtxdist[mype]; for (i=0; i=0 && elmnts[i].key=vtxdist[mype] && elmnts[i].valwhere[elmnts[i].val-firstvtx] = elmnts[i].key; } GKfree((void **)&mypicks, (void **)&allpicks, (void **)&perm, LTERM); if (wspace->nlarge < nrecv) free(relmnts); }