int kgraphStoreInit ( const Kgraph * const grafptr, KgraphStore * const storptr) { ArchDom domnfrst; /* Largest domain in the architecture */ archDomFrst (&grafptr->a, &domnfrst); /* Get architecture domain */ storptr->partnbr = (Gnum) archDomSize (&grafptr->a, &domnfrst); /* Get architecture size */ if (memAllocGroup ((void **) (void *) /* Allocate save structure */ &storptr->parttab, (size_t) (grafptr->s.vertnbr * sizeof (Anum)), &storptr->domntab, (size_t) (grafptr->m.domnmax * sizeof (ArchDom)), &storptr->frontab, (size_t) (grafptr->s.vertnbr * sizeof (Gnum)), &storptr->comploadavg, (size_t) (storptr->partnbr * sizeof (Gnum)), &storptr->comploaddlt, (size_t) (storptr->partnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("kgraphStoreInit out of memory (1)"); return (1); } return (0); }
int SCOTCH_graphMapView ( const SCOTCH_Graph * const libgrafptr, const SCOTCH_Mapping * const libmappptr, FILE * const stream) { const Graph * restrict grafptr; const Mapping * restrict mappptr; Anum * restrict parttax; /* Part array */ MappingSort * restrict domntab; /* Pointer to domain sort array */ ArchDom domnfrst; /* Largest domain in architecture */ Anum tgtnbr; /* Number of processors in target topology */ Anum mapnbr; /* Number of processors effectively used */ Anum mapnum; double mapavg; /* Average mapping weight */ Gnum mapmin; Gnum mapmax; Gnum mapsum; /* (Partial) sum of vertex loads */ double mapdlt; double mapmmy; /* Maximum / average ratio */ Anum * restrict nghbtab; /* Table storing neighbors of current subdomain */ Anum nghbnbr; Anum nghbmin; Anum nghbmax; Anum nghbsum; Gnum vertnum; Gnum veloval; Gnum edloval; Gnum commdist[256]; /* Array of load distribution */ Gnum commload; /* Total edge load (edge sum) */ Gnum commdilat; /* Total edge dilation */ Gnum commexpan; /* Total edge expansion */ Anum distmax; Anum distval; Gnum diammin; Gnum diammax; Gnum diamsum; const Gnum * restrict const verttax = ((Graph *) libgrafptr)->verttax; const Gnum * restrict const vendtax = ((Graph *) libgrafptr)->vendtax; const Gnum * restrict const velotax = ((Graph *) libgrafptr)->velotax; const Gnum * restrict const edgetax = ((Graph *) libgrafptr)->edgetax; const Gnum * restrict const edlotax = ((Graph *) libgrafptr)->edlotax; grafptr = (Graph *) libgrafptr; mappptr = &((LibMapping *) libmappptr)->m; if ((grafptr->vertnbr == 0) || /* Return if nothing to do */ (grafptr->edgenbr == 0)) return (0); if (memAllocGroup ((void **) (void *) &domntab, (size_t) ((grafptr->vertnbr + 1) * sizeof (MappingSort)), &parttax, (size_t) (grafptr->vertnbr * sizeof (Anum)), &nghbtab, (size_t) ((grafptr->vertnbr + 2) * sizeof (Anum)), NULL) == NULL) { errorPrint ("SCOTCH_graphMapView: out of memory"); return (1); } memSet (parttax, ~0, grafptr->vertnbr * sizeof (Anum)); for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { parttax[vertnum] = domntab[vertnum].labl = archDomNum (&mappptr->archdat, mapDomain (mappptr, vertnum + grafptr->baseval)); domntab[vertnum].peri = vertnum + grafptr->baseval; /* Build inverse permutation */ } domntab[grafptr->vertnbr].labl = ARCHDOMNOTTERM; /* TRICK: avoid testing (i+1) */ domntab[grafptr->vertnbr].peri = ~0; /* Prevent Valgrind from yelling */ parttax -= grafptr->baseval; /* From now on, base part array */ intSort2asc2 (domntab, grafptr->vertnbr); /* Sort domain label array by increasing target labels */ archDomFrst (&mappptr->archdat, &domnfrst); /* Get architecture domain */ tgtnbr = archDomSize (&mappptr->archdat, &domnfrst); /* Get architecture size */ mapsum = 0; mapnbr = 0; veloval = 1; /* Assume unweighted vertices */ for (vertnum = 0; domntab[vertnum].labl != ARCHDOMNOTTERM; vertnum ++) { parttax[domntab[vertnum].peri] = mapnbr; /* Build map of partition parts starting from 0 */ if (domntab[vertnum].labl != domntab[vertnum + 1].labl) /* TRICK: if new (or end) domain label */ mapnbr ++; if (velotax != NULL) veloval = velotax[domntab[vertnum].peri]; mapsum += veloval; } mapavg = (mapnbr == 0) ? 0.0L : (double) mapsum / (double) mapnbr; mapsum = 0; mapmin = GNUMMAX; mapmax = 0; mapdlt = 0.0L; for (vertnum = 0; domntab[vertnum].labl != ARCHDOMNOTTERM; vertnum ++) { if (velotax != NULL) veloval = velotax[domntab[vertnum].peri]; mapsum += veloval; if (domntab[vertnum].labl != domntab[vertnum + 1].labl) { /* TRICK: if new (or end) domain label */ if (mapsum < mapmin) mapmin = mapsum; if (mapsum > mapmax) mapmax = mapsum; mapdlt += fabs ((double) mapsum - mapavg); mapsum = 0; /* Reset domain load sum */ } } mapdlt = (mapnbr != 0) ? mapdlt / ((double) mapnbr * mapavg) : 0.0L; mapmmy = (mapnbr != 0) ? (double) mapmax / (double) mapavg : 0.0L; if (mapnbr > tgtnbr) { /* If more subdomains than architecture size */ #ifdef SCOTCH_DEBUG_MAP2 if (! archVar (&mappptr->archdat)) { /* If not a variable-sized architecture */ errorPrint ("SCOTCH_graphMapView: invalid mapping"); memFree (domntab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_MAP2 */ tgtnbr = mapnbr; /* Assume it is a variable-sized architecture */ } fprintf (stream, "M\tProcessors " GNUMSTRING "/" GNUMSTRING " (%g)\n", (Gnum) mapnbr, (Gnum) tgtnbr, (double) mapnbr / (double) tgtnbr); fprintf (stream, "M\tTarget min=" GNUMSTRING "\tmax=" GNUMSTRING "\tavg=%g\tdlt=%g\tmaxavg=%g\n", (Gnum) mapmin, (Gnum) mapmax, mapavg, mapdlt, mapmmy); nghbnbr = 0; nghbmin = ANUMMAX; nghbmax = 0; nghbsum = 0; nghbnbr = 0; nghbtab[0] = -2; for (vertnum = 0; domntab[vertnum].labl != ARCHDOMNOTTERM; vertnum ++) { Gnum edgenum; Gnum edgennd; Anum partnum; partnum = parttax[domntab[vertnum].peri]; for (edgenum = verttax[domntab[vertnum].peri], edgennd = vendtax[domntab[vertnum].peri]; edgenum < edgennd; edgenum ++) { Anum partend; partend = parttax[edgetax[edgenum]]; if ((partend != partnum) && /* If edge is not internal */ (partend != nghbtab[nghbnbr])) { /* And neighbor is not sole neighbor or has not just been found */ Anum partmin; Anum partmax; partmin = 0; partmax = nghbnbr; while ((partmax - partmin) > 1) { Anum partmed; partmed = (partmax + partmin) >> 1; if (nghbtab[partmed] > partend) partmax = partmed; else partmin = partmed; } if (nghbtab[partmin] == partend) /* If neighboring part found, skip to next neighbor */ continue; #ifdef SCOTCH_DEBUG_MAP2 if (nghbnbr >= (grafptr->vertnbr + 1)) { errorPrint ("SCOTCH_graphMapView: internal error"); return (1); } #endif /* SCOTCH_DEBUG_MAP2 */ nghbnbr ++; for (partmax = nghbnbr; partmax > (partmin + 1); partmax --) nghbtab[partmax] = nghbtab[partmax - 1]; nghbtab[partmin + 1] = partend; /* Add new neighbor part in the right place */ } } if (domntab[vertnum].labl != domntab[vertnum + 1].labl) { /* TRICK: if new (or end) domain label */ if (nghbnbr < nghbmin) nghbmin = nghbnbr; if (nghbnbr > nghbmax) nghbmax = nghbnbr; nghbsum += nghbnbr; nghbnbr = 0; } }
int C_mapLoad ( C_Mapping * const mapptr, FILE * const stream) { C_VertSort * vertsorttab; /* Pointer to graph sorting array */ int vertsortflag; /* Flag set if graph data sorted by label */ C_VertSort * mapsorttab; /* Pointer to mapping data sorting array */ int mapsortflag; /* Flag set if mapping data sorted by label */ SCOTCH_Num mapsortval; /* Value of maximum size for compatibility */ SCOTCH_Num mapfileval; /* Value of maximum size for compatibility */ SCOTCH_Num mapfilenbr; /* Number of mapping pairs in file */ SCOTCH_Num * mapfiletab; /* Pointer to mapping data read from file */ SCOTCH_Num i, j; if ((mapptr->labltab == NULL) && /* Allocate array if necessary */ ((mapptr->labltab = (SCOTCH_Num *) memAlloc (mapptr->grafptr->vertnbr * sizeof (SCOTCH_Num))) == NULL)) { errorPrint ("C_mapLoad: out of memory (1)"); return (1); } memset (mapptr->labltab, ~0, mapptr->grafptr->vertnbr * sizeof (SCOTCH_Num)); /* Pre-initialize mapping */ if (stream == NULL) /* If stream is invalid */ return (0); if ((fscanf (stream, SCOTCH_NUMSTRING, /* Read number of mapping pairs */ &mapfileval) != 1) || (mapfileval < 1)) { errorPrint ("C_mapLoad: bad input (1)"); return (1); } mapfilenbr = (SCOTCH_Num) mapfileval; if (memAllocGroup ((void **) (void *) &mapfiletab, (size_t) (mapfilenbr * sizeof (SCOTCH_Num)), &mapsorttab, (size_t) (mapfilenbr * sizeof (C_VertSort)), &vertsorttab, (size_t) (mapptr->grafptr->vertnbr * sizeof (C_VertSort)), NULL) == NULL) { errorPrint ("C_mapLoad: out of memory (2)"); return (1); } mapsortflag = 1; /* Assume mapping data sorted */ for (i = 0; i < mapfilenbr; i ++) { if (fscanf (stream, SCOTCH_NUMSTRING SCOTCH_NUMSTRING, &mapsortval, &mapfileval) != 2) { errorPrint ("C_mapLoad: bad input (2)"); memFree (mapfiletab); /* Free group leader */ return (1); } mapsorttab[i].labl = mapsortval; mapsorttab[i].num = i; mapfiletab[i] = mapfileval; if ((i > 0) && /* Check if mapping data sorted */ (mapsorttab[i].labl < mapsorttab[i - 1].labl)) mapsortflag = 0; /* Mapping data not sorted */ } if (mapsortflag != 1) /* If mapping data not sorted */ qsort ((char *) mapsorttab, mapfilenbr, /* Sort sort area by ascending labels */ sizeof (C_VertSort), (int (*) (const void *, const void *)) C_geoLoad2); for (i = 1; i < mapfilenbr; i ++) { /* Check mapping data integrity */ if (mapsorttab[i].labl == mapsorttab[i - 1].labl) { errorPrint ("C_mapLoad: duplicate vertex label"); memFree (mapfiletab); /* Free group leader */ return (1); } } if (mapptr->grafptr->vlbltab != NULL) { /* If graph has vertex labels */ vertsortflag = 1; /* Assume graph data sorted */ for (i = 0; i < mapptr->grafptr->vertnbr; i ++) { vertsorttab[i].labl = mapptr->grafptr->vlbltab[i]; vertsorttab[i].num = i; if ((i > 0) && /* Check if graph data sorted */ (vertsorttab[i].labl < vertsorttab[i - 1].labl)) vertsortflag = 0; /* Graph data not sorted */ } if (vertsortflag != 1) /* If graph data not sorted */ qsort ((char *) vertsorttab, mapptr->grafptr->vertnbr, /* Sort sort area by ascending labels */ sizeof (C_VertSort), (int (*) (const void *, const void *)) C_geoLoad2); } else { /* Graph does not have vertex labels */ for (i = 0; i < mapptr->grafptr->vertnbr; i ++) { vertsorttab[i].labl = i + mapptr->grafptr->baseval; vertsorttab[i].num = i; } } for (i = 0, j = 0; i < mapptr->grafptr->vertnbr; i ++) { /* For all vertices in graph */ while ((j < mapfilenbr) && (mapsorttab[j].labl < vertsorttab[i].labl)) j ++; /* Search mapping vertex with same label */ if ((j >= mapfilenbr) || (mapsorttab[j].labl > vertsorttab[i].labl)) /* If label does not exist */ continue; /* This vertex has no related mapping data */ mapptr->labltab[vertsorttab[i].num] = mapfiletab[mapsorttab[j ++].num]; } memFree (mapfiletab); /* Free group leader */ return (0); }
int C_geoLoad ( C_Geometry * const geomptr, FILE * const stream) { C_VertSort * vertsorttab; /* Pointer to graph sorting array */ int vertsortflag; /* Flag set if graph data sorted by label */ C_VertSort * geomsorttab; /* Pointer to geometric data sorting array */ int geomsortflag; /* Flag set if geometric data sorted by label */ int geomfiletype; /* Type of geometry file */ SCOTCH_Num geomfilenbr; /* Number of geometric coordinates in file */ SCOTCH_Num geomfileval; /* Value of maximum size for compatibility */ C_GeoVert * geomfiletab; /* Pointer to geometric data read from file */ SCOTCH_Num vertlablval; /* Value of maximum size for compatibility */ SCOTCH_Num i, j; int o; if ((geomptr->verttab == NULL) && /* Allocate geometry if necessary */ ((geomptr->verttab = (C_GeoVert *) memAlloc (geomptr->grafptr->vertnbr * sizeof (C_GeoVert))) == NULL)) { errorPrint ("C_geoLoad: out of memory (1)"); return (1); } if ((fscanf (stream, "%d" SCOTCH_NUMSTRING, /* Read type and number of geometry items */ &geomfiletype, &geomfileval) != 2) || (geomfiletype < 1) || (geomfiletype > 3) || (geomfileval < 1)) { errorPrint ("C_geoLoad: bad input (1)"); return (1); } geomfilenbr = (SCOTCH_Num) geomfileval; if (memAllocGroup ((void **) (void *) &geomfiletab, (size_t) (geomfilenbr * sizeof (C_GeoVert)), &geomsorttab, (size_t) (geomfilenbr * sizeof (C_VertSort)), &vertsorttab, (size_t) (geomptr->grafptr->vertnbr * sizeof (C_VertSort)), NULL) == NULL) { errorPrint ("C_geoLoad: out of memory (2)"); return (1); } o = 0; geomsortflag = 1; /* Assume geometry data sorted */ switch (geomfiletype) { case 1 : /* Load 2D coordinates array */ for (i = 0; (i < geomfilenbr) && (o == 0); i ++) { if (fscanf (stream, SCOTCH_NUMSTRING "%lf", &vertlablval, &geomfiletab[i].x) != 2) o = 1; geomsorttab[i].labl = (SCOTCH_Num) vertlablval; geomfiletab[i].y = /* No Y and Z coordinates */ geomfiletab[i].z = 0.0; geomsorttab[i].num = i; if (C_geoFlag & C_GEOFLAGROTATE) { /* Rotate picture if necessary */ double t; /* Temporary swap variable */ t = geomfiletab[i].y; geomfiletab[i].y = geomfiletab[i].x; geomfiletab[i].x = - t; } if ((i > 0) && /* Check if geometry data sorted */ (geomsorttab[i].labl < geomsorttab[i - 1].labl)) geomsortflag = 0; /* Geometry data not sorted */ } break; case 2 : /* Load 2D coordinates array */ for (i = 0; (i < geomfilenbr) && (o == 0); i ++) { if (fscanf (stream, SCOTCH_NUMSTRING "%lf%lf", &vertlablval, &geomfiletab[i].x, &geomfiletab[i].y) != 3) o = 1; geomsorttab[i].labl = (SCOTCH_Num) vertlablval; geomfiletab[i].z = 0.0; /* No Z coordinate */ geomsorttab[i].num = i; if (C_geoFlag & C_GEOFLAGROTATE) { /* Rotate picture if necessary */ double t; /* Temporary swap variable */ t = geomfiletab[i].y; geomfiletab[i].y = geomfiletab[i].x; geomfiletab[i].x = - t; } if ((i > 0) && /* Check if geometry data sorted */ (geomsorttab[i].labl < geomsorttab[i - 1].labl)) geomsortflag = 0; /* Geometry data are not sorted */ } break; case 3 : /* Load 3D coordinates array */ for (i = 0; (i < geomfilenbr) && (o == 0); i ++) { if (fscanf (stream, SCOTCH_NUMSTRING "%lf%lf%lf", &vertlablval, &geomfiletab[i].x, &geomfiletab[i].y, &geomfiletab[i].z) != 4) o = 1; geomsorttab[i].labl = (SCOTCH_Num) vertlablval; geomsorttab[i].num = i; if (C_geoFlag & C_GEOFLAGPERMUT) { /* Rotate picture if necessary */ double t; /* Temporary swap variable */ t = geomfiletab[i].z; geomfiletab[i].z = geomfiletab[i].y; geomfiletab[i].y = t; } if ((i > 0) && /* Check if geometry data sorted */ (geomsorttab[i].labl < geomsorttab[i - 1].labl)) geomsortflag = 0; /* Geometry data not sorted */ } break; default : errorPrint ("C_geoLoad: invalid geometry type (%d)", geomfiletype); memFree (geomfiletab); /* Free group leader */ return (1); } if (o != 0) { errorPrint ("C_geoLoad: bad input (2)"); memFree (geomfiletab); /* Free group leader */ return (1); } if (geomsortflag != 1) /* If geometry data not sorted */ qsort ((char *) geomsorttab, geomfilenbr, /* Sort sort area by ascending labels */ sizeof (C_VertSort), (int (*) (const void *, const void *)) C_geoLoad2); for (i = 1; i < geomfilenbr; i ++) { /* Check geometric data integrity */ if (geomsorttab[i].labl == geomsorttab[i - 1].labl) { errorPrint ("C_geoLoad: duplicate vertex label"); memFree (geomfiletab); /* Free group leader */ return (1); } } if (geomptr->grafptr->vlbltab != NULL) { /* If graph has vertex labels */ vertsortflag = 1; /* Assume graph data sorted */ for (i = 0; i < geomptr->grafptr->vertnbr; i ++) { vertsorttab[i].labl = geomptr->grafptr->vlbltab[i]; vertsorttab[i].num = i; if ((i > 0) && /* Check if graph data sorted */ (vertsorttab[i].labl < vertsorttab[i - 1].labl)) vertsortflag = 0; /* Graph data not sorted */ } if (vertsortflag != 1) /* If graph data not sorted */ qsort ((char *) vertsorttab, geomptr->grafptr->vertnbr, /* Sort sort area by ascending labels */ sizeof (C_VertSort), (int (*) (const void *, const void *)) C_geoLoad2); } else { /* Graph does not have vertex labels */ for (i = 0; i < geomptr->grafptr->vertnbr; i ++) { vertsorttab[i].labl = i + geomsorttab[0].labl; /* Use first index as base value */ vertsorttab[i].num = i; } } for (i = 0, j = 0; i < geomptr->grafptr->vertnbr; i ++) { /* For all vertices in graph */ while ((j < geomfilenbr) && (geomsorttab[j].labl < vertsorttab[i].labl)) j ++; /* Search geometry vertex with same label */ if ((j >= geomfilenbr) || (geomsorttab[j].labl > vertsorttab[i].labl)) { /* If label does not exist */ errorPrint ("C_geoLoad: vertex geometry data not found for label '" SCOTCH_NUMSTRING "'", vertsorttab[i].labl); memFree (geomfiletab); /* Free group leader */ return (1); } geomptr->verttab[vertsorttab[i].num] = geomfiletab[geomsorttab[j ++].num]; } memFree (geomfiletab); /* Free group leader */ return (0); }
int SCOTCH_dgraphMapView ( SCOTCH_Dgraph * const libgrafptr, const SCOTCH_Dmapping * const libmappptr, FILE * const stream) { Dgraph * restrict grafptr; const LibDmapping * restrict mappptr; ArchDom domnfrst; /* Largest domain in architecture */ unsigned int * restrict nmskloctab; /* Local neighbor bitfield */ unsigned int * restrict nmskglbtab; /* Local neighbor bitfield */ int nmskidxnbr; /* Size of bitfield; int since sent by MPI */ Gnum * restrict tgloloctab; /* Local array of terminal domain loads */ Gnum * restrict tgloglbtab; /* Global array of terminal domain loads */ Gnum * restrict termgsttax; /* Terminal domain ghost mapping array */ Anum tgtnbr; /* Number of processors in target topology */ Anum tgtnum; Anum mapnbr; /* Number of processors effectively used */ double mapavg; /* Average mapping weight */ Gnum mapmin; Gnum mapmax; Gnum mapsum; /* (Partial) sum of vertex loads */ double mapdlt; double mapmmy; /* Maximum / average ratio */ Anum ngbsum; Anum ngbmin; Anum ngbmax; Gnum vertlocnum; Gnum veloval; Gnum edloval; Gnum commlocdist[256 + 3]; /* Array of local load distribution */ Gnum commglbdist[256 + 3]; Gnum commlocload; /* Total local edge load (edge sum) */ Gnum commlocdilat; /* Total edge dilation */ Gnum commlocexpan; /* Total edge expansion */ Anum distmax; Anum distval; int cheklocval; int chekglbval; DgraphHaloRequest requdat; grafptr = (Dgraph *) libgrafptr; mappptr = (LibDmapping *) libmappptr; if ((grafptr->vertglbnbr == 0) || /* Return if nothing to do */ (grafptr->edgeglbnbr == 0)) return (0); archDomFrst (&mappptr->m.archdat, &domnfrst); /* Get architecture domain */ tgtnbr = archDomSize (&mappptr->m.archdat, &domnfrst); /* Get architecture size */ if (archVar (&mappptr->m.archdat)) { errorPrint ("SCOTCH_dgraphMapView: not implemented"); return (1); } if (dgraphGhst (grafptr) != 0) { /* Compute ghost edge array if not already present */ errorPrint ("SCOTCH_dgraphMapView: cannot compute ghost edge array"); return (1); } nmskidxnbr = (tgtnbr + 1 + ((sizeof (int) << 3) - 1)) / (sizeof (int) << 3); /* Size of neighbor subdomain bitfield; TRICK: "+1" to have a "-1" cell for unmapped vertices */ cheklocval = 0; if (memAllocGroup ((void **) (void *) &nmskloctab, (size_t) (nmskidxnbr * sizeof (unsigned int)), &nmskglbtab, (size_t) (nmskidxnbr * sizeof (unsigned int)), &tgloloctab, (size_t) ((tgtnbr + 1) * sizeof (Gnum)), /* TRICK: "+1" to have a "-1" cell for unmapped vertices */ &tgloglbtab, (size_t) (tgtnbr * sizeof (Gnum)), &termgsttax, (size_t) (grafptr->vertgstnbr * sizeof (Gnum)), NULL) == NULL) { cheklocval = 1; } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("SCOTCH_dgraphMapView: communication error (1)"); return (1); } if (chekglbval != 0) { if (nmskloctab != NULL) memFree (nmskloctab); errorPrint ("SCOTCH_dgraphMapView: out of memory"); return (1); } if (dmapTerm (&mappptr->m, grafptr, termgsttax) != 0) { errorPrint ("SCOTCH_dgraphMapView: cannot build local terminal array"); memFree (nmskloctab); return (1); } dgraphHaloAsync (grafptr, termgsttax, GNUM_MPI, &requdat); termgsttax -= grafptr->baseval; memSet (tgloloctab, 0, (tgtnbr + 1) * sizeof (Gnum)); tgloloctab ++; /* TRICK: trim array for "-1" cell */ veloval = 1; for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { #ifdef SCOTCH_DEBUG_DMAP2 if ((termgsttax[vertlocnum] < -1) || (termgsttax[vertlocnum] >= tgtnbr)) { errorPrint ("SCOTCH_dgraphMapView: invalid local terminal array"); memFree (nmskloctab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_DMAP2 */ if (grafptr->veloloctax != NULL) veloval = grafptr->veloloctax[vertlocnum]; tgloloctab[termgsttax[vertlocnum]] += veloval; /* One more vertex of given weight assigned to this target */ } if (MPI_Allreduce (tgloloctab, tgloglbtab, tgtnbr, GNUM_MPI, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("SCOTCH_dgraphMapView: communication error (2)"); memFree (nmskloctab); /* Free group leader */ return (1); } mapmin = GNUMMAX; mapmax = 0; mapsum = 0; mapnbr = 0; for (tgtnum = 0; tgtnum < tgtnbr; tgtnum ++) { Gnum tgtsum; tgtsum = tgloglbtab[tgtnum]; if (tgtsum != 0) { mapnbr ++; mapsum += tgtsum; if (tgtsum < mapmin) mapmin = tgtsum; if (tgtsum > mapmax) mapmax = tgtsum; } } mapavg = (mapnbr == 0) ? 0.0L : ((double) mapsum / (double) mapnbr); mapdlt = 0.0L; for (tgtnum = 0; tgtnum < tgtnbr; tgtnum ++) mapdlt += fabs ((double) tgloglbtab[tgtnum] - mapavg); mapdlt = (mapnbr != 0) ? mapdlt / ((double) mapnbr * mapavg) : 0.0L; mapmmy = (mapnbr != 0) ? (double) mapmax / (double) mapavg : 0.0L; if (stream != NULL) { fprintf (stream, "M\tProcessors " GNUMSTRING "/" GNUMSTRING "(%g)\n", (Gnum) mapnbr, (Gnum) tgtnbr, (double) mapnbr / (double) tgtnbr); fprintf (stream, "M\tTarget min=" GNUMSTRING "\tmax=" GNUMSTRING "\tavg=%g\tdlt=%g\tmaxavg=%g\n", (Gnum) mapmin, (Gnum) mapmax, mapavg, mapdlt, mapmmy); } if (dgraphHaloWait (&requdat) != 0) { /* Wait for ghost terminal data to be exchanged */ errorPrint ("SCOTCH_dgraphMapView: cannot complete asynchronous halo exchange"); memFree (nmskloctab); /* Free group leader */ return (1); } ngbmin = ANUMMAX; ngbmax = 0; ngbsum = 0; for (tgtnum = 0; tgtnum < tgtnbr; tgtnum ++) { /* For all subdomain indices */ int nmskidxnum; Gnum vertlocnum; Anum ngbnbr; if (tgloglbtab[tgtnum] <= 0) /* If empty subdomain, skip it */ continue; memSet (nmskloctab, 0, nmskidxnbr * sizeof (int)); /* Reset neighbor bit mask */ for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { /* For all local vertices */ Gnum termnum; Gnum edgelocnum; Gnum edgelocnnd; termnum = termgsttax[vertlocnum]; if (termnum != tgtnum) /* If vertex does not belong to current part or is not mapped, skip it */ continue; for (edgelocnum = grafptr->vertloctax[vertlocnum], edgelocnnd = grafptr->vendloctax[vertlocnum]; edgelocnum < edgelocnnd; edgelocnum ++) { Gnum termend; termend = termgsttax[grafptr->edgegsttax[edgelocnum]]; if (termend != tgtnum) { /* If edge is not internal */ termend ++; /* TRICK: turn unmapped to 0 and so on */ nmskloctab[termend / (sizeof (int) << 3)] |= 1 << (termend & ((sizeof (int) << 3) - 1)); /* Flag neighbor in bit array */ } } } nmskloctab[0] &= ~1; /* Do not account for unmapped vertices (terminal domain 0 because of "+1") */ if (MPI_Allreduce (nmskloctab, nmskglbtab, nmskidxnbr, MPI_INT, MPI_BOR, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("SCOTCH_dgraphMapView: communication error (3)"); memFree (nmskloctab); /* Free group leader */ return (1); } for (nmskidxnum = 0, ngbnbr = 0; nmskidxnum < nmskidxnbr; nmskidxnum ++) { unsigned int nmskbitval; for (nmskbitval = nmskglbtab[nmskidxnum]; nmskbitval != 0; nmskbitval >>= 1) ngbnbr += nmskbitval & 1; } ngbsum += ngbnbr; if (ngbnbr < ngbmin) ngbmin = ngbnbr; if (ngbnbr > ngbmax) ngbmax = ngbnbr; } if (stream != NULL) { fprintf (stream, "M\tNeighbors min=" GNUMSTRING "\tmax=" GNUMSTRING "\tsum=" GNUMSTRING "\n", (Gnum) ngbmin, (Gnum) ngbmax, (Gnum) ngbsum); } memSet (commlocdist, 0, 256 * sizeof (Gnum)); /* Initialize the data */ commlocload = commlocdilat = commlocexpan = 0; edloval = 1; for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { /* For all local vertices */ Gnum termlocnum; ArchDom termdomdat; Gnum edgelocnum; Gnum edgelocnnd; termlocnum = termgsttax[vertlocnum]; if (termlocnum == ~0) /* Skip unmapped vertices */ continue; archDomTerm (&mappptr->m.archdat, &termdomdat, termlocnum); for (edgelocnum = grafptr->vertloctax[vertlocnum], edgelocnnd = grafptr->vendloctax[vertlocnum]; edgelocnum < edgelocnnd; edgelocnum ++) { ArchDom termdomend; Gnum termgstend; Anum distval; termgstend = termgsttax[grafptr->edgegsttax[edgelocnum]]; if (termgstend == ~0) /* Skip unmapped end vertices */ continue; distval = 0; if (grafptr->edloloctax != NULL) /* Get edge weight if any */ edloval = grafptr->edloloctax[edgelocnum]; if (termgstend != termlocnum) { /* If not same domain, compute distance */ archDomTerm (&mappptr->m.archdat, &termdomend, termgstend); distval = archDomDist (&mappptr->m.archdat, &termdomdat, &termdomend); } commlocdist[(distval > 255) ? 255 : distval] += edloval; commlocload += edloval; commlocdilat += distval; commlocexpan += distval * edloval; } } commlocdist[256] = commlocload; commlocdist[256 + 1] = commlocdilat; commlocdist[256 + 2] = commlocexpan; if (MPI_Allreduce (commlocdist, commglbdist, 256 + 3, GNUM_MPI, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("SCOTCH_dgraphMapView: communication error (4)"); memFree (nmskloctab); /* Free group leader */ return (1); } if (stream != NULL) { Gnum commglbload; commglbload = commglbdist[256]; fprintf (stream, "M\tCommDilat=%f\t(" GNUMSTRING ")\n", /* Print expansion parameters */ (double) commglbdist[256 + 1] / grafptr->edgeglbnbr, (Gnum) (commglbdist[256 + 1] / 2)); fprintf (stream, "M\tCommExpan=%f\t(" GNUMSTRING ")\n", ((commglbload == 0) ? (double) 0.0L : (double) commglbdist[256 + 2] / (double) commglbload), (Gnum) (commglbdist[256 + 2] / 2)); fprintf (stream, "M\tCommCutSz=%f\t(" GNUMSTRING ")\n", ((commglbload == 0) ? (double) 0.0L : (double) (commglbload - commglbdist[0]) / (double) commglbload), (Gnum) ((commglbload - commglbdist[0]) / 2)); fprintf (stream, "M\tCommDelta=%f\n", (((double) commglbload * (double) commglbdist[256 + 1]) == 0.0L) ? (double) 0.0L : ((double) commglbdist[256 + 2] * (double) grafptr->edgeglbnbr) / ((double) commglbload * (double) commglbdist[256 + 2])); for (distmax = 255; distmax != -1; distmax --) /* Find longest distance */ if (commglbdist[distmax] != 0) break; for (distval = 0; distval <= distmax; distval ++) /* Print distance histogram */ fprintf (stream, "M\tCommLoad[" ANUMSTRING "]=%f\n", (Anum) distval, (double) commglbdist[distval] / (double) commglbload); } memFree (nmskloctab); /* Free group leader */ return (0); }
int main ( int argc, char * argv[]) { SCOTCH_Graph grafdat; SCOTCH_Num vertnbr; SCOTCH_Num * verttab; SCOTCH_Num * vendtab; SCOTCH_Num edgenbr; SCOTCH_Num * edgetab; SCOTCH_Num baseval; SCOTCH_Ordering ordedat; SCOTCH_Num * permtab; SCOTCH_Num * peritab; int i; errorProg ("gotst"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give help */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "gotst, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ SCOTCH_graphInit (&grafdat); SCOTCH_graphLoad (&grafdat, C_filepntrgrfinp, -1, 3); SCOTCH_graphData (&grafdat, &baseval, &vertnbr, &verttab, &vendtab, NULL, NULL, &edgenbr, &edgetab, NULL); #ifdef SCOTCH_DEBUG_ALL if (vendtab != (verttab + 1)) { errorPrint ("main: graph should be compact"); return (1); } #endif /* SCOTCH_DEBUG_ALL */ if (memAllocGroup ((void **) (void *) &peritab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), &permtab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), NULL) == NULL) { errorPrint ("main: out of memory"); return (1); } SCOTCH_graphOrderInit (&grafdat, &ordedat, permtab, peritab, NULL, NULL, NULL); SCOTCH_graphOrderLoad (&grafdat, &ordedat, C_filepntrordinp); if (SCOTCH_graphOrderCheck (&grafdat, &ordedat) != 0) { errorPrint ("main: invalid ordering"); return (1); } factorView (baseval, vertnbr, verttab, edgenbr, edgetab, permtab, peritab, C_filepntrdatout); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ memFree (peritab); SCOTCH_graphOrderExit (&grafdat, &ordedat); SCOTCH_graphExit (&grafdat); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); }
int bdgraphBipartDf ( Bdgraph * const grafptr, /*+ Distributed graph +*/ const BdgraphBipartDfParam * const paraptr) /*+ Method parameters +*/ { float * restrict ielsloctax; /* Inverse of degree array */ float * restrict veexloctax; /* Veexval over domdist */ float * restrict difogsttax; /* Old diffusion value array */ float * restrict difngsttax; /* New diffusion value array */ const Gnum * restrict edgegsttax; Gnum fronlocnum; Gnum veexlocnbr; float vanclocval[2]; float valolocval[2]; /* Fraction of load to remove from anchor vertices at each step */ Gnum vanclocnnd; Gnum vertlocnum; const Gnum * restrict velolocbax; Gnum velolocmsk; const Gnum * restrict edlolocbax; Gnum edlolocmsk; Gnum complocload1; Gnum complocsize1; Gnum commlocloadintn; Gnum commlocloadextn; Gnum commlocgainextn; Gnum reduloctab[6]; Gnum reduglbtab[6]; Gnum passnum; float cdifval; float cremval; int ovflval; /* Overflow flag value */ if (dgraphGhst (&grafptr->s) != 0) { /* Compute ghost edge array if not already present */ errorPrint ("bdgraphBipartDf: cannot compute ghost edge array"); return (1); } reduloctab[0] = grafptr->s.vendloctax[grafptr->s.vertlocnnd - 2] - grafptr->s.vertloctax[grafptr->s.vertlocnnd - 2] - (grafptr->s.procglbnbr - 1); /* Local degree of both anchor vertices, minus edges to other anchors */ reduloctab[1] = grafptr->s.vendloctax[grafptr->s.vertlocnnd - 1] - grafptr->s.vertloctax[grafptr->s.vertlocnnd - 1] - (grafptr->s.procglbnbr - 1); /* Anchor edges have load 1 even for weighted graphs */ if (grafptr->s.veloloctax == NULL) reduloctab[2] = /* Weights of anchors */ reduloctab[3] = 1; else { reduloctab[2] = grafptr->s.veloloctax[grafptr->s.vertlocnnd - 2]; reduloctab[3] = grafptr->s.veloloctax[grafptr->s.vertlocnnd - 1]; } veexlocnbr = (grafptr->veexloctax != NULL) ? grafptr->s.vertlocnbr : 0; if (memAllocGroup ((void **) (void *) &ielsloctax, (size_t) (grafptr->s.vertlocnbr * sizeof (float)), &veexloctax, (size_t) (veexlocnbr * sizeof (float)), &difogsttax, (size_t) (grafptr->s.vertgstnbr * sizeof (float)), &difngsttax, (size_t) (grafptr->s.vertgstnbr * sizeof (float)), NULL) == NULL) { errorPrint ("bdgraphBipartDf: out of memory"); reduloctab[0] = -1; } ielsloctax -= grafptr->s.baseval; difogsttax -= grafptr->s.baseval; difngsttax -= grafptr->s.baseval; veexloctax = (grafptr->veexloctax != NULL) ? (veexloctax - grafptr->s.baseval) : NULL; if (MPI_Allreduce (reduloctab, reduglbtab, 4, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartDf: communication error (1)"); return (1); } if (reduglbtab[0] < 0) { if (ielsloctax != NULL) memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ return (1); } if ((reduglbtab[0] == 0) || /* If graph is too small to have any usable anchors, leave partition as is */ (reduglbtab[1] == 0)) { memFree (ielsloctax + grafptr->s.baseval); if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (grafptr->partgsttax + grafptr->s.baseval), GRAPHPART_MPI) != 0) { errorPrint ("bdgraphBipartDf: cannot propagate part data (1)"); return (1); } return (0); } vanclocval[0] = (float) ((paraptr->typeval == BDGRAPHBIPARTDFTYPEBAL) /* If balanced parts wanted */ ? grafptr->compglbload0avg /* Target is average */ : ( (grafptr->compglbload0 < grafptr->compglbload0min) ? grafptr->compglbload0min : /* Else keep load if not off balance */ ((grafptr->compglbload0 > grafptr->compglbload0max) ? grafptr->compglbload0max : grafptr->compglbload0))); vanclocval[1] = (float) grafptr->s.veloglbsum - vanclocval[0]; vanclocval[0] = - vanclocval[0]; /* Part 0 holds negative values */ valolocval[0] = (float) reduglbtab[2]; /* Compute values to remove from anchor vertices */ valolocval[1] = (float) reduglbtab[3] - BDGRAPHBIPARTDFEPSILON; /* Slightly tilt value to add to part 1 */ vanclocnnd = grafptr->s.vertlocnnd - 2; /* Do not account for anchor vertices in diffusion computations */ if (grafptr->s.edloloctax != NULL) { for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) { Gnum edgelocnum; Gnum edgelocnnd; Gnum edlolocsum; #ifdef SCOTCH_DEBUG_BDGRAPH2 if ((grafptr->s.vendloctax[vertlocnum] - grafptr->s.vertloctax[vertlocnum]) == 0) { errorPrint ("bdgraphBipartDf: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ difogsttax[vertlocnum] = 0.0F; for (edgelocnum = grafptr->s.vertloctax[vertlocnum], edgelocnnd = grafptr->s.vendloctax[vertlocnum], edlolocsum = 0; edgelocnum < edgelocnnd; edgelocnum ++) edlolocsum += grafptr->s.edloloctax[edgelocnum]; ielsloctax[vertlocnum] = 1.0F / (float) edlolocsum; } } else { /* Graph has no edge loads */ for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) { #ifdef SCOTCH_DEBUG_BDGRAPH2 if ((grafptr->s.vendloctax[vertlocnum] - grafptr->s.vertloctax[vertlocnum]) == 0) { errorPrint ("bdgraphBipartDf: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ ielsloctax[vertlocnum] = 1.0F / (float) (grafptr->s.vendloctax[vertlocnum] - grafptr->s.vertloctax[vertlocnum]); difogsttax[vertlocnum] = 0.0F; } } ielsloctax[vanclocnnd] = 1.0F / (float) reduglbtab[0]; ielsloctax[vanclocnnd + 1] = 1.0F / (float) reduglbtab[1]; difogsttax[vanclocnnd] = vanclocval[0] * ielsloctax[vanclocnnd]; /* Load anchor vertices for first pass */ difogsttax[vanclocnnd + 1] = vanclocval[1] * ielsloctax[vanclocnnd + 1]; difngsttax[vanclocnnd] = /* In case of isolated anchors, do not risk overflow because of NaN */ difngsttax[vanclocnnd + 1] = 0.0F; if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (difogsttax + grafptr->s.baseval), MPI_FLOAT) != 0) { /* Perform initial diffusion (and build communication structures) */ errorPrint ("bdgraphBipartDf: cannot propagate diffusion data (1)"); memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ return (1); } ovflval = 0; cdifval = paraptr->cdifval; cremval = paraptr->cremval; edgegsttax = grafptr->s.edgegsttax; for (passnum = 0; ; ) { /* For all passes */ if (ovflval == 0) { /* If no overflow occured */ float * diftgsttax; /* Temporary swap value */ Gnum vertlocnum; float veloval; veloval = 1.0F; /* Assume no vertex loads */ for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) { Gnum edgelocnum; Gnum edgelocnnd; float diffval; diffval = 0.0F; edgelocnum = grafptr->s.vertloctax[vertlocnum]; edgelocnnd = grafptr->s.vendloctax[vertlocnum]; if (grafptr->s.edloloctax != NULL) for ( ; edgelocnum < edgelocnnd; edgelocnum ++) diffval += difogsttax[edgegsttax[edgelocnum]] * (float) grafptr->s.edloloctax[edgelocnum]; else for ( ; edgelocnum < edgelocnnd; edgelocnum ++) diffval += difogsttax[edgegsttax[edgelocnum]]; diffval *= cdifval; diffval += (difogsttax[vertlocnum] * cremval) / ielsloctax[vertlocnum]; if (grafptr->s.veloloctax != NULL) veloval = (float) grafptr->s.veloloctax[vertlocnum]; if (diffval >= 0.0F) { diffval = (diffval - veloval) * ielsloctax[vertlocnum]; if (diffval <= 0.0F) diffval = +BDGRAPHBIPARTDFEPSILON; } else { diffval = (diffval + veloval) * ielsloctax[vertlocnum]; if (diffval >= 0.0F) diffval = -BDGRAPHBIPARTDFEPSILON; } if (isnan (diffval)) { /* If overflow occured */ ovflval = 1; /* We are in state of overflow */ goto abort; /* Exit this loop without swapping arrays */ } difngsttax[vertlocnum] = diffval; } for ( ; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { /* For the two local anchor vertices */ Gnum edgelocnum; Gnum edgelocnnd; float diffval; diffval = 0.0F; edgelocnum = grafptr->s.vertloctax[vertlocnum] + grafptr->s.procglbnbr - 1; /* Skip links to other anchors */ edgelocnnd = grafptr->s.vendloctax[vertlocnum]; if (edgelocnum == edgelocnnd) /* If isolated anchor */ continue; /* Barrel is empty */ for ( ; edgelocnum < edgelocnnd; edgelocnum ++) /* Anchor edges have load 1 even for weighted graphs */ diffval += difogsttax[edgegsttax[edgelocnum]]; diffval *= cdifval; diffval += vanclocval[vertlocnum - vanclocnnd] + (difogsttax[vertlocnum] * cremval) / ielsloctax[vertlocnum]; if (diffval >= 0.0F) { diffval = (diffval - valolocval[vertlocnum - vanclocnnd]) * ielsloctax[vertlocnum]; if (diffval <= 0.0F) diffval = +BDGRAPHBIPARTDFEPSILON; } else { diffval = (diffval + valolocval[vertlocnum - vanclocnnd]) * ielsloctax[vertlocnum]; if (diffval >= 0.0F) diffval = -BDGRAPHBIPARTDFEPSILON; } if (isnan (diffval)) { /* If overflow occured */ ovflval = 1; /* We are in state of overflow */ goto abort; /* Exit this loop without swapping arrays */ } difngsttax[vertlocnum] = diffval; } diftgsttax = (float *) difngsttax; /* Swap old and new diffusion arrays */ difngsttax = (float *) difogsttax; /* Casts to prevent IBM compiler from yelling */ difogsttax = (float *) diftgsttax; } abort : /* If overflow occured, resume here */ if (++ passnum >= paraptr->passnbr) /* If maximum number of passes reached */ break; /* Exit main loop */ if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (difogsttax + grafptr->s.baseval), MPI_FLOAT) != 0) { errorPrint ("bdgraphBipartDf: cannot propagate diffusion data (2)"); memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ return (1); } } for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) /* Set new part distribution */ grafptr->partgsttax[vertlocnum] = (difogsttax[vertlocnum] <= 0.0F) ? 0 : 1; grafptr->partgsttax[vanclocnnd] = 0; /* Set up parts in case anchors are isolated */ grafptr->partgsttax[vanclocnnd + 1] = 1; if (grafptr->s.veloloctax != NULL) { velolocbax = grafptr->s.veloloctax; velolocmsk = ~((Gnum) 0); } else { velolocbax = &bdgraphbipartdfloadone; velolocmsk = 0; } if (grafptr->s.edloloctax != NULL) { edlolocbax = grafptr->s.edloloctax; edlolocmsk = ~((Gnum) 0); } else { edlolocbax = &bdgraphbipartdfloadone; edlolocmsk = 0; } memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (grafptr->partgsttax + grafptr->s.baseval), GRAPHPART_MPI) != 0) { errorPrint ("bdgraphBipartDf: cannot propagate part data (2)"); return (1); } commlocloadintn = commlocloadextn = commlocgainextn = 0; for (vertlocnum = grafptr->s.baseval, fronlocnum = complocsize1 = complocload1 = 0; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { Gnum edgelocnum; Gnum edgelocnnd; Gnum veloval; Gnum partval; Gnum flagval; #ifdef SCOTCH_DEBUG_BDGRAPH2 if (grafptr->partgsttax[vertlocnum] > 1) { errorPrint ("bdgraphBipartDf: internal error (3)"); break; /* Do not break upcoming collective communications */ } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ partval = (Gnum) grafptr->partgsttax[vertlocnum]; veloval = velolocbax[vertlocnum & velolocmsk]; if (grafptr->veexloctax != NULL) { commlocloadextn += grafptr->veexloctax[vertlocnum] * partval; commlocgainextn += grafptr->veexloctax[vertlocnum] * (1 - partval * 2); } complocsize1 += partval; complocload1 += partval * veloval; flagval = 0; for (edgelocnum = grafptr->s.vertloctax[vertlocnum], edgelocnnd = grafptr->s.vendloctax[vertlocnum]; edgelocnum < edgelocnnd; edgelocnum ++) { Gnum edloval; Gnum partend; partend = (Gnum) grafptr->partgsttax[edgegsttax[edgelocnum]]; #ifdef SCOTCH_DEBUG_BDGRAPH2 if (partend > 1) { errorPrint ("bdgraphBipartDf: internal error (4)"); vertlocnum = grafptr->s.vertlocnnd; break; /* Do not break upcoming collective communications */ } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ edloval = edlolocbax[edgelocnum & edlolocmsk]; flagval |= partval ^ partend; commlocloadintn += (partval ^ partend) * edloval; /* Internal load is accounted for twice */ } if (flagval != 0) /* If vertex has neighbors in other part */ grafptr->fronloctab[fronlocnum ++] = vertlocnum; /* Record it as member of separator */ } grafptr->complocload0 = grafptr->s.velolocsum - complocload1; grafptr->complocsize0 = grafptr->s.vertlocnbr - complocsize1; grafptr->fronlocnbr = fronlocnum; reduloctab[0] = fronlocnum; reduloctab[1] = grafptr->complocload0; reduloctab[2] = grafptr->complocsize0; reduloctab[3] = commlocloadintn; /* Twice the internal load; sum globally before dividing by two */ reduloctab[4] = commlocloadextn; reduloctab[5] = commlocgainextn; if (MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 6, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartDf: communication error (2)"); return (1); } grafptr->fronglbnbr = reduglbtab[0]; grafptr->compglbload0 = reduglbtab[1]; grafptr->compglbload0dlt = grafptr->compglbload0 - grafptr->compglbload0avg; grafptr->compglbsize0 = reduglbtab[2]; grafptr->commglbload = (reduglbtab[3] / 2) * grafptr->domdist + reduglbtab[4]; grafptr->commglbgainextn = reduglbtab[5]; #ifdef SCOTCH_DEBUG_BDGRAPH2 if (bdgraphCheck (grafptr) != 0) { errorPrint ("bdgraphBipartDf: internal error (5)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ return (0); }
int main ( int argc, char * argv[]) { SCOTCH_Graph grafdat; SCOTCH_Num vertnbr; SCOTCH_Num * verttab; SCOTCH_Num * vendtab; SCOTCH_Num edgenbr; SCOTCH_Num * edgetab; SCOTCH_Num baseval; SCOTCH_Ordering ordedat; SCOTCH_Num * permtab; SCOTCH_Num * peritab; int i; errorProg ("order_eval"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '+') && /* If found a file name */ ((argv[i][0] != '-') || (argv[i][1] == '\0'))) { if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give help */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "order_eval, from gotst, version 5 - F. Pellegrini\n"); fprintf (stderr, "Copyright 2004,2007 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option (\"%s\")", argv[i]); return (1); } } } for (i = 0; i < C_FILENBR; i ++) { /* For all file names */ if ((C_fileTab[i].name[0] != '-') || /* If not standard stream */ (C_fileTab[i].name[1] != '\0')) { if ((C_fileTab[i].pntr = fopen (C_fileTab[i].name, C_fileTab[i].mode)) == NULL) { /* Open the file */ errorPrint ("main: cannot open file (%d)", i); return (1); } } } SCOTCH_graphInit (&grafdat); graphLoadMM (&grafdat, C_filepntrgrfinp); SCOTCH_graphData (&grafdat, &baseval, &vertnbr, &verttab, &vendtab, NULL, NULL, &edgenbr, &edgetab, NULL); #ifdef SCOTCH_DEBUG_ALL if (vendtab != (verttab + 1)) { errorPrint ("main: graph should be compact"); return (1); } #endif /* SCOTCH_DEBUG_ALL */ if (memAllocGroup ((void **) &peritab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), &permtab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), NULL) == NULL) { errorPrint ("main: out of memory"); return (1); } SCOTCH_graphOrderInit (&grafdat, &ordedat, permtab, peritab, NULL, NULL, NULL); SCOTCH_graphOrderLoad (&grafdat, &ordedat, C_filepntrordinp); if (SCOTCH_graphOrderCheck (&grafdat, &ordedat) != 0) { errorPrint ("main: invalid ordering"); return (1); } factorView (baseval, vertnbr, verttab, edgenbr, edgetab, permtab, peritab, C_filepntrdatout); #ifdef SCOTCH_DEBUG_ALL memFree (peritab); SCOTCH_graphOrderExit (&grafdat, &ordedat); SCOTCH_graphExit (&grafdat); for (i = 0; i < C_FILENBR; i ++) { /* For all file names */ if ((C_fileTab[i].name[0] != '-') || /* If not standard stream */ (C_fileTab[i].name[1] != '\0')) { fclose (C_fileTab[i].pntr); /* Close the stream */ } } #endif /* SCOTCH_DEBUG_ALL */ return (0); }
void METISNAMEU(ParMETIS_V3_NodeND) ( const int * const vtxdist, int * const xadj, int * const adjncy, const int * const numflag, const int * const options, /* Not used */ int * const order, int * const sizes, /* Of size twice the number of processors ; not used */ MPI_Comm * comm) { MPI_Comm proccomm; int procglbnbr; int proclocnum; SCOTCH_Num baseval; SCOTCH_Dgraph grafdat; /* Scotch distributed graph object to interface with libScotch */ SCOTCH_Dordering ordedat; /* Scotch distributed ordering object to interface with libScotch */ SCOTCH_Strat stradat; SCOTCH_Num vertlocnbr; SCOTCH_Num edgelocnbr; if (sizeof (SCOTCH_Num) != sizeof (int)) { SCOTCH_errorPrint ("ParMETIS_V3_NodeND (as of SCOTCH): SCOTCH_Num type should equate to int"); return; } proccomm = *comm; if (SCOTCH_dgraphInit (&grafdat, proccomm) != 0) return; MPI_Comm_size (proccomm, &procglbnbr); MPI_Comm_rank (proccomm, &proclocnum); baseval = *numflag; vertlocnbr = vtxdist[proclocnum + 1] - vtxdist[proclocnum]; edgelocnbr = xadj[vertlocnbr] - baseval; if (sizes != NULL) memSet (sizes, ~0, (2 * procglbnbr - 1) * sizeof (int)); /* Array not used if procglbnbr is not a power of 2 or if error */ if (SCOTCH_dgraphBuild (&grafdat, baseval, vertlocnbr, vertlocnbr, xadj, xadj + 1, NULL, NULL, edgelocnbr, edgelocnbr, adjncy, NULL, NULL) == 0) { SCOTCH_stratInit (&stradat); #ifdef SCOTCH_DEBUG_ALL if (SCOTCH_dgraphCheck (&grafdat) == 0) /* TRICK: next instruction called only if graph is consistent */ #endif /* SCOTCH_DEBUG_ALL */ { if (SCOTCH_dgraphOrderInit (&grafdat, &ordedat) == 0) { int levlmax; int bitsnbr; SCOTCH_Num proctmp; SCOTCH_dgraphOrderCompute (&grafdat, &ordedat, &stradat); SCOTCH_dgraphOrderPerm (&grafdat, &ordedat, order); for (levlmax = -1, bitsnbr = 0, proctmp = procglbnbr; /* Count number of bits set to 1 in procglbnbr */ proctmp != 0; levlmax ++, proctmp >>= 1) bitsnbr += proctmp & 1; if (bitsnbr == 1) { SCOTCH_Num cblkglbnbr; if ((cblkglbnbr = SCOTCH_dgraphOrderCblkDist (&grafdat, &ordedat)) >= 0) { SCOTCH_Num * treeglbtab; SCOTCH_Num * sizeglbtab; SCOTCH_Num * sepaglbtab; if (memAllocGroup ((void **) (void *) &treeglbtab, (size_t) (cblkglbnbr * sizeof (SCOTCH_Num)), &sizeglbtab, (size_t) (cblkglbnbr * sizeof (SCOTCH_Num)), &sepaglbtab, (size_t) (cblkglbnbr * sizeof (SCOTCH_Num) * 3), NULL) != NULL) { if (SCOTCH_dgraphOrderTreeDist (&grafdat, &ordedat, treeglbtab, sizeglbtab) == 0) { SCOTCH_Num rootnum; SCOTCH_Num cblknum; memSet (sepaglbtab, ~0, cblkglbnbr * sizeof (SCOTCH_Num) * 3); for (rootnum = -1, cblknum = 0; cblknum < cblkglbnbr; cblknum ++) { SCOTCH_Num fathnum; fathnum = treeglbtab[cblknum] - baseval; /* Use un-based indices */ if (fathnum < 0) { /* If father index indicates root */ if (rootnum != -1) { /* If another root already found */ rootnum = -1; /* Indicate an error */ break; } rootnum = cblknum; /* Record index of root node */ } else { int i; for (i = 0; i < 3; i ++) { int j; j = 3 * fathnum + i; /* Slot number of prospective son */ if (sepaglbtab[j] < 0) { /* If potentially empty slot found */ if (sepaglbtab[j] == -1) /* If we don't have too many sons */ sepaglbtab[j] = cblknum; /* Add link to son in slot */ break; } } if (i == 3) { /* If no empty slot found */ sepaglbtab[3 * fathnum] = -2; /* Indicate there are too many sons */ break; } } } if ((rootnum >= 0) && (sizes != NULL)) { /* If no error above, go on processing separator tree */ memSet (sizes, 0, (2 * procglbnbr - 1) * sizeof (int)); /* Set array of sizes to 0 by default */ _SCOTCH_ParMETIS_V3_NodeNDTree (sizes + (2 * procglbnbr - 1), sizeglbtab, sepaglbtab, levlmax, 0, rootnum, 1); } } memFree (treeglbtab); /* Free group leader */ } } } SCOTCH_dgraphOrderExit (&grafdat, &ordedat); } }