Example #1
0
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;
    }
  }
Example #3
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);
}
Example #4
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);
}
Example #6
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);
}
Example #8
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);
      }
    }