Skip to content

Commit

Permalink
Fixed a memory bug in coarsening
Browse files Browse the repository at this point in the history
  • Loading branch information
karypis committed Nov 27, 2020
1 parent 36262ad commit 38a8fb0
Show file tree
Hide file tree
Showing 5 changed files with 0 additions and 367 deletions.
352 changes: 0 additions & 352 deletions libmetis/coarsen.c
Original file line number Diff line number Diff line change
Expand Up @@ -1063,358 +1063,6 @@ void CreateCoarseGraph(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs,
}


/*************************************************************************/
/*! This function creates the coarser graph. It uses a full-size array
(htable) for identifying the adjacent vertices that get collapsed to
the same node.
*/
/*************************************************************************/
void CreateCoarseGraphNoMask(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs,
idx_t *match)
{
idx_t j, k, m, istart, iend, v, u, nvtxs, nedges, ncon, cnedges;
idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt;
idx_t *cmap, *htable;
idx_t *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt;
graph_t *cgraph;
int dovsize, dropedges;
idx_t cv, nkeep, droppedewgt;
idx_t *keys=NULL, *medianewgts=NULL, *noise=NULL;

WCOREPUSH;

dovsize = (ctrl->objtype == METIS_OBJTYPE_VOL ? 1 : 0);
dropedges = ctrl->dropedges;

IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ContractTmr));

nvtxs = graph->nvtxs;
ncon = graph->ncon;
xadj = graph->xadj;
vwgt = graph->vwgt;
vsize = graph->vsize;
adjncy = graph->adjncy;
adjwgt = graph->adjwgt;
cmap = graph->cmap;

/* Setup structures for dropedges */
if (dropedges) {
for (nkeep=-1, v=0; v<nvtxs; v++)
nkeep = gk_max(nkeep, xadj[v+1]-xadj[v]);

medianewgts = iwspacemalloc(ctrl, cnvtxs);
noise = iwspacemalloc(ctrl, cnvtxs);
keys = iwspacemalloc(ctrl, 2*(nkeep+1));

for (v=0; v<cnvtxs; v++)
noise[v] = irandInRange(128);
}

/* Initialize the coarser graph */
cgraph = SetupCoarseGraph(graph, cnvtxs, dovsize);
cxadj = cgraph->xadj;
cvwgt = cgraph->vwgt;
cvsize = cgraph->vsize;
cadjncy = cgraph->adjncy;
cadjwgt = cgraph->adjwgt;

htable = iset(cnvtxs, -1, iwspacemalloc(ctrl, cnvtxs));

cxadj[0] = cnvtxs = cnedges = 0;
for (v=0; v<nvtxs; v++) {
if ((u = match[v]) < v)
continue;

ASSERT(cmap[v] == cnvtxs);
ASSERT(cmap[match[v]] == cnvtxs);

if (ncon == 1)
cvwgt[cnvtxs] = vwgt[v];
else
icopy(ncon, vwgt+v*ncon, cvwgt+cnvtxs*ncon);

if (dovsize)
cvsize[cnvtxs] = vsize[v];

nedges = 0;

istart = xadj[v];
iend = xadj[v+1];
for (j=istart; j<iend; j++) {
k = cmap[adjncy[j]];
if ((m = htable[k]) == -1) {
cadjncy[nedges] = k;
cadjwgt[nedges] = adjwgt[j];
htable[k] = nedges++;
}
else {
cadjwgt[m] += adjwgt[j];
}
}

if (v != u) {
if (ncon == 1)
cvwgt[cnvtxs] += vwgt[u];
else
iaxpy(ncon, 1, vwgt+u*ncon, 1, cvwgt+cnvtxs*ncon, 1);

if (dovsize)
cvsize[cnvtxs] += vsize[u];

istart = xadj[u];
iend = xadj[u+1];
for (j=istart; j<iend; j++) {
k = cmap[adjncy[j]];
if ((m = htable[k]) == -1) {
cadjncy[nedges] = k;
cadjwgt[nedges] = adjwgt[j];
htable[k] = nedges++;
}
else {
cadjwgt[m] += adjwgt[j];
}
}

/* Remove the contracted adjacency weight */
if ((j = htable[cnvtxs]) != -1) {
ASSERT(cadjncy[j] == cnvtxs);
cadjncy[j] = cadjncy[--nedges];
cadjwgt[j] = cadjwgt[nedges];
htable[cnvtxs] = -1;
}
}

/* Zero out the htable */
for (j=0; j<nedges; j++)
htable[cadjncy[j]] = -1;


/* Determine the median weight of the incident edges, which will be used
to keep an edge (u, v) iff wgt(u, v) >= min(medianewgts[u], medianewgts[v]) */
if (dropedges) {
for (j=0; j<nedges; j++)
keys[j] = (cadjwgt[j]<<8) + noise[cnvtxs] + noise[cadjncy[j]];
isortd(nedges, keys);
medianewgts[cnvtxs] = keys[((xadj[v+1]-xadj[v] + xadj[u+1]-xadj[u])>>1)];
}

/* Record Advance the cadjXXX pointers */
cadjncy += nedges;
cadjwgt += nedges;
cnedges += nedges;
cxadj[++cnvtxs] = cnedges;
}


/* compact the adjacency structure of the coarser graph to keep only +ve edges */
if (dropedges) {
droppedewgt = 0;

cadjncy = cgraph->adjncy;
cadjwgt = cgraph->adjwgt;

cnedges = 0;
for (u=0; u<cnvtxs; u++) {
istart = cxadj[u];
iend = cxadj[u+1];
for (j=istart; j<iend; j++) {
v = cadjncy[j];
if ((cadjwgt[j]<<8) + noise[u] + noise[v] >= gk_min(medianewgts[u], medianewgts[v])) {
cadjncy[cnedges] = cadjncy[j];
cadjwgt[cnedges++] = cadjwgt[j];
}
else
droppedewgt += cadjwgt[j];
}
cxadj[u] = cnedges;
}
SHIFTCSR(j, cnvtxs, cxadj);

//printf("droppedewgt: %d\n", (int)droppedewgt);

cgraph->droppedewgt = droppedewgt;
}

cgraph->nedges = cnedges;

for (j=0; j<ncon; j++) {
cgraph->tvwgt[j] = isum(cgraph->nvtxs, cgraph->vwgt+j, ncon);
cgraph->invtvwgt[j] = 1.0/(cgraph->tvwgt[j] > 0 ? cgraph->tvwgt[j] : 1);
}

ReAdjustMemory(ctrl, graph, cgraph);

IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ContractTmr));

WCOREPOP;
}


/*************************************************************************/
/*! This function creates the coarser graph. It uses a simple hash-table
for identifying the adjacent vertices that get collapsed to the same
node. The hash-table can have conflicts, which are handled via a
linear scan. It relies on the perm[] array to visit the vertices in
increasing cnvtxs order.
*/
/*************************************************************************/
void CreateCoarseGraphPerm(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs,
idx_t *match, idx_t *perm)
{
idx_t i, j, jj, k, kk, l, m, istart, iend, nvtxs, nedges, ncon, cnedges,
v, u, mask, dovsize;
idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt;
idx_t *cmap, *htable;
idx_t *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt;
graph_t *cgraph;

WCOREPUSH;

IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ContractTmr));

dovsize = (ctrl->objtype == METIS_OBJTYPE_VOL ? 1 : 0);

mask = HTLENGTH;

nvtxs = graph->nvtxs;
ncon = graph->ncon;
xadj = graph->xadj;
vwgt = graph->vwgt;
vsize = graph->vsize;
adjncy = graph->adjncy;
adjwgt = graph->adjwgt;
cmap = graph->cmap;

/* Initialize the coarser graph */
cgraph = SetupCoarseGraph(graph, cnvtxs, dovsize);
cxadj = cgraph->xadj;
cvwgt = cgraph->vwgt;
cvsize = cgraph->vsize;
cadjncy = cgraph->adjncy;
cadjwgt = cgraph->adjwgt;

htable = iset(mask+1, -1, iwspacemalloc(ctrl, mask+1));

cxadj[0] = cnvtxs = cnedges = 0;
for (i=0; i<nvtxs; i++) {
v = perm[i];
if (cmap[v] != cnvtxs)
continue;

u = match[v];
if (ncon == 1)
cvwgt[cnvtxs] = vwgt[v];
else
icopy(ncon, vwgt+v*ncon, cvwgt+cnvtxs*ncon);

if (dovsize)
cvsize[cnvtxs] = vsize[v];

nedges = 0;

istart = xadj[v];
iend = xadj[v+1];
for (j=istart; j<iend; j++) {
k = cmap[adjncy[j]];
kk = k&mask;
if ((m = htable[kk]) == -1) {
cadjncy[nedges] = k;
cadjwgt[nedges] = adjwgt[j];
htable[kk] = nedges++;
}
else if (cadjncy[m] == k) {
cadjwgt[m] += adjwgt[j];
}
else {
for (jj=0; jj<nedges; jj++) {
if (cadjncy[jj] == k) {
cadjwgt[jj] += adjwgt[j];
break;
}
}
if (jj == nedges) {
cadjncy[nedges] = k;
cadjwgt[nedges++] = adjwgt[j];
}
}
}

if (v != u) {
if (ncon == 1)
cvwgt[cnvtxs] += vwgt[u];
else
iaxpy(ncon, 1, vwgt+u*ncon, 1, cvwgt+cnvtxs*ncon, 1);

if (dovsize)
cvsize[cnvtxs] += vsize[u];

istart = xadj[u];
iend = xadj[u+1];
for (j=istart; j<iend; j++) {
k = cmap[adjncy[j]];
kk = k&mask;
if ((m = htable[kk]) == -1) {
cadjncy[nedges] = k;
cadjwgt[nedges] = adjwgt[j];
htable[kk] = nedges++;
}
else if (cadjncy[m] == k) {
cadjwgt[m] += adjwgt[j];
}
else {
for (jj=0; jj<nedges; jj++) {
if (cadjncy[jj] == k) {
cadjwgt[jj] += adjwgt[j];
break;
}
}
if (jj == nedges) {
cadjncy[nedges] = k;
cadjwgt[nedges++] = adjwgt[j];
}
}
}

/* Remove the contracted adjacency weight */
jj = htable[cnvtxs&mask];
if (jj >= 0 && cadjncy[jj] != cnvtxs) {
for (jj=0; jj<nedges; jj++) {
if (cadjncy[jj] == cnvtxs)
break;
}
}
if (jj >= 0 && cadjncy[jj] == cnvtxs) { /* This 2nd check is needed for non-adjacent matchings */
cadjncy[jj] = cadjncy[--nedges];
cadjwgt[jj] = cadjwgt[nedges];
}
}

for (j=0; j<nedges; j++)
htable[cadjncy[j]&mask] = -1; /* Zero out the htable */
htable[cnvtxs&mask] = -1;

cnedges += nedges;
cxadj[++cnvtxs] = cnedges;
cadjncy += nedges;
cadjwgt += nedges;
}

cgraph->nedges = cnedges;

for (i=0; i<ncon; i++) {
cgraph->tvwgt[i] = isum(cgraph->nvtxs, cgraph->vwgt+i, ncon);
cgraph->invtvwgt[i] = 1.0/(cgraph->tvwgt[i] > 0 ? cgraph->tvwgt[i] : 1);
}


ReAdjustMemory(ctrl, graph, cgraph);

IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ContractTmr));

WCOREPOP;
}


/*************************************************************************/
/*! Setup the various arrays for the coarse graph
*/
Expand Down
4 changes: 0 additions & 4 deletions libmetis/kmetis.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ int METIS_PartGraphKway(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy,
graph_t *graph;
ctrl_t *ctrl;

#ifdef XXX
/* set up malloc cleaning code and signal catchers */
if (!gk_malloc_init())
return METIS_ERROR_MEMORY;
Expand All @@ -33,7 +32,6 @@ int METIS_PartGraphKway(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy,

if ((sigrval = gk_sigcatch()) != 0)
goto SIGTHROW;
#endif

/* set up the run parameters */
ctrl = SetupCtrl(METIS_OP_KMETIS, options, *ncon, *nparts, tpwgts, ubvec);
Expand Down Expand Up @@ -87,10 +85,8 @@ int METIS_PartGraphKway(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy,
if (renumber)
Change2FNumbering(*nvtxs, xadj, adjncy, part);

#ifdef XXX
gk_siguntrap();
gk_malloc_cleanup(0);
#endif

return metis_rcode(sigrval);
}
Expand Down

0 comments on commit 38a8fb0

Please sign in to comment.