Beispiel #1
0
int
Zoltan_PHG_2ways_hyperedge_partition (
  ZZ *zz,                            /* Input : Zoltan data structure */
  HGraph *hg,
  Partition parts,
  Zoltan_PHG_Tree *tree,
  struct Zoltan_DD_Struct * gnoToGID,
  struct Zoltan_DD_Struct **dd,
  int *numParts,
  int **sizeParts
)
{
  int ierr = ZOLTAN_OK;
  char *yo = "Zoltan_PHG_2ways_hyperedge_partition";
  int nEdge, hEdge;
  int *interval;
  int *partnumber = NULL;
  int tree_size;
  int *rowpart =NULL;
  int *rowGNO = NULL;
  ZOLTAN_ID_PTR rowGID=NULL;
  int index;
  int offset;

  ZOLTAN_TRACE_ENTER(zz, yo);

  nEdge = hg->nEdge;
  fprintf (stderr, "HG (%d %d x %d) : %d %d\n", hg->comm->myProc, hg->comm->myProc_x, hg->comm->myProc_y,  hg->nVtx, nEdge);

  interval = (int*)ZOLTAN_MALLOC(nEdge*2*sizeof(int));
  if ((nEdge > 0 ) && (interval == NULL)) MEMORY_ERROR;

  tree_size = get_tree_size(tree) + 1;
  for (index = 0 ; index < nEdge ; ++index){
    SET_MIN_NODE(interval, index, tree_size);
    SET_MAX_NODE(interval, index, -1);
  }

  /* Update interval with the local knowledge */
  /* XXX: I loop on the hyperedges, as I think it's more cache friendly
   * and it allows me to discoupled the computation if a non blocking MPI_Reduce is
   * available
   */
  for (hEdge = 0 ; hEdge < nEdge ; ++hEdge){
    int part;
    int max = -1;                     /* Trick : we use the initialized values */
    int min = tree_size + 1;

    for (index = hg->hindex[hEdge] ; index < hg->hindex[hEdge+1] ; ++ index) {
      part = parts[hg->hvertex[index]];

      max = MAX(max, part);
      min = MIN(min, part);
    }
    SET_MIN_NODE(interval, hEdge, min);
    SET_MAX_NODE(interval, hEdge, max);
  }

  /* Update results to view the complete hyperedges */
  Zoltan_AllReduceInPlace (interval, 2*nEdge, MPI_INT, MPI_MAX, hg->comm->row_comm);

  /* Now I have to compute the partition of hyperedges according to the "interval"
   * and the tree */

  /* First, compute the partition number corresponding to the nodes in the tree */
  partnumber = compute_part_number(tree);
  if (partnumber == NULL) {
    ierr = ZOLTAN_FATAL;
    goto End;
  }

  (*numParts) = get_tree_size(tree);

  rowpart = (int*) ZOLTAN_MALLOC(nEdge*sizeof(int));
  if ((nEdge > 0) && (rowpart == NULL)) MEMORY_ERROR;

  rowGNO = (int*) ZOLTAN_MALLOC(nEdge*sizeof(int));
  if ((nEdge > 0) && (rowGNO == NULL)) MEMORY_ERROR;

  (*sizeParts) = (int*)ZOLTAN_CALLOC((*numParts), sizeof(int));
  if (*numParts && (*sizeParts) == NULL) MEMORY_ERROR;

  offset = hg->dist_y[hg->comm->myProc_y];
  /* Then we search we is the hyperedge in the tree */
  for (hEdge = 0 ; hEdge < nEdge ; ++hEdge) {
    int node;
    node = find_interval_in_tree(tree, interval+2*hEdge);
    rowpart[hEdge] = partnumber[node];
    (*sizeParts)[rowpart[hEdge]] ++;
    rowGNO[hEdge] = EDGE_LNO_TO_GNO(hg, hEdge);
#if 0
    fprintf (stderr, "%d : %d (%d : %d - %d)\n", rowGNO[hEdge], rowpart[hEdge], node, -interval[2*hEdge], interval[2*hEdge+1]);
#endif
  }

  partnumber += 1;
  ZOLTAN_FREE(&partnumber);
  ZOLTAN_FREE(&interval);

  /* Compute number of elements per parts */
  /* TODO: support processor which are not part of the distribution */

  /* Update results to view the complete hyperedges */
  Zoltan_AllReduceInPlace ((*sizeParts), (*numParts), MPI_INT, MPI_SUM, hg->comm->col_comm);


  /* Export results to data directory */
  /* First, get the GIDs of our edges */
  rowGID = ZOLTAN_MALLOC_GID_ARRAY(zz, nEdge);
  if (nEdge && rowGID == NULL) MEMORY_ERROR;
  ierr = Zoltan_DD_Find (gnoToGID , (ZOLTAN_ID_PTR)rowGNO, rowGID, NULL, NULL,
			 nEdge, NULL);
  ZOLTAN_FREE(&rowGNO);

  ierr = Zoltan_DD_Create (dd, zz->Communicator, zz->Num_GID, 1, 0, nEdge, 0);
  CHECK_IERR;

  /* Make our new numbering public */
  Zoltan_DD_Update (*dd, (ZOLTAN_ID_PTR)rowGID, (ZOLTAN_ID_PTR) rowpart, NULL,  NULL, nEdge);

#ifdef CEDRIC_PRINT
  for (hEdge = 0 ; hEdge < nEdge ; ++hEdge) {
    fprintf (stderr, "%d : %d\n", rowGID[hEdge], rowpart[hEdge]);
  }
#endif


 End:
  ZOLTAN_FREE(&rowGID);
  ZOLTAN_FREE(&rowGNO);
  ZOLTAN_FREE(&rowpart);

  if (partnumber != NULL)
    partnumber += 1;
  ZOLTAN_FREE(&partnumber);
  ZOLTAN_FREE(&interval);

  ZOLTAN_TRACE_EXIT(zz, yo);

  return (ierr);
}
Beispiel #2
0
void print_hypergraph(ZZ *zz, ZHG *zhg, int sumWeight)
{
  int i, j, npins;
  int ewdim = zz->Edge_Weight_Dim;
  int vwdim = zhg->objWeightDim;
  float sum;
  float *wgt, *vwgt;
  int *pin, *owner, *lno;
  HGraph *hg = &zhg->HG;
  int p = zz->Proc;

  /* The ZHG structure contains the hypergraph returned by the query functions,
   * including modifications based on ADD_OBJ_WEIGHT and PHG_EDGE_WEIGHT_OPERATION.
   * If the PHG hypergraph build has completed, the edge list only contains the removed
   * edges.  If LB_Eval build the ZHG structure, it contains all edges.
   *
   * the HGraph structure contains that hypergraph with modifications made
   * for the PHG algorithm.  This may include addition of repartition
   * vertices and edges, and removal of dense edges.
   */

  wgt = zhg->objWeight;

  printf("(%d) %d INPUT VERTICES (out of %d) : gno (gid/lid) (weights) nhedges fixed inpart outpart objSize)\n",p, zhg->nObj, zhg->globalObj);

  for (i=0; i<zhg->nObj; i++){

    printf("  %d (",zhg->objGNO[i]);

    if (zhg->objGID)
      printf("%d/",zhg->objGID[i]);
    else
      printf("-/");

    if (zhg->objLID)
      printf("%d) (",zhg->objLID[i]);
    else
      printf("/-) (");

    for (j=0; j < vwdim; j++){
      printf("%f",*wgt++);
      if (j < vwdim-1) printf(", ");
    }

    if (zhg->numHEdges)
      printf(") %d ",zhg->numHEdges[i]);
    else
      printf(") - ");

    if (zhg->fixed)
      printf(" %d ",zhg->fixed[i]);
    else
      printf(" - ");

    if (zhg->Input_Parts)
      printf(" %d ",zhg->Input_Parts[i]);
    else
      printf(" - ");

    if (zhg->Output_Parts)
      printf(" %d ",zhg->Output_Parts[i]);
    else
      printf(" - ");

    if (zhg->AppObjSizes)
      printf(" %d ",zhg->AppObjSizes[i]);
    else
      printf(" - ");

    printf("\n");
  }
  printf("\n");
 
  wgt = zhg->Ewgt;
  pin = zhg->pinGNO;
  owner = zhg->Pin_Procs;
   
  printf("(%d) %d INPUT or REMOVED EDGES (out of %d), %d pins: gno size (weights) (pinGNO/pinProc)\n",
                  p, zhg->nHedges, zhg->globalHedges, zhg->nPins);

  for (i=0; i < zhg->nHedges; i++){

    printf("  %d %d (", zhg->edgeGNO[i], zhg->Esize[i]);

    if (wgt){
      for (j=0; j < ewdim; j++){
        printf("%f",*wgt++);
        if (j < ewdim - 1) printf(", ");
      }
    }
    printf(") (");

    for (j=0; j < zhg->Esize[i]; j++){
      printf("%d/%d", *pin++, *owner++);
      if (j < zhg->Esize[i] - 1) printf(" ");
    }

    printf(")\n");
  }
  printf("\n");

  printf("(%d) %d PHG EDGES (%d weights), %d total PHG PINS:\n",
          p, hg->nEdge, ewdim, hg->nPins);

  wgt = hg->ewgt;
  lno = hg->hvertex;
  vwgt = hg->vwgt;

  for (i=0; i<hg->nEdge; i++){
    npins = hg->hindex[i+1] - hg->hindex[i];

    printf(" edge %d: ",EDGE_LNO_TO_GNO(hg, i));
    for (j=0; j<ewdim; j++){
      printf(" %f",*wgt++);
    }
    printf("\n %d pins: ", npins);
    for (j=0; j<npins; j++){
      printf("%d ", *lno++);
    }
    printf("\n");
  }
  printf("\n");

  printf("(%d) %d PHG PIN global numbers and %d weights:\n", p, hg->nVtx, vwdim);

  sum = 0;

  for (i=0; i<hg->nVtx; i++){
    printf("  %d  %d: ", i, VTX_LNO_TO_GNO(hg, i));
    for (j=0; j<vwdim; j++){
      if (j==sumWeight) sum += *vwgt;
      printf("%f ", *vwgt++);
    }
    printf("\n");
  }
  printf("\n");
  if (sum > 0.0) printf("(%d) Weight %d sums to %f\n\n",p, sumWeight+1,sum);
}
Beispiel #3
0
void Zoltan_HG_Print(
  ZZ *zz,
  HGraph *hg,
  Partition parts,
  FILE *fp,
  char *str
)
{
/* Routine to print hypergraph weights and edges. Assumes serial execution;
 * put inside Zoltan_Print_Sync_Start/Zoltan_Print_Sync_End for parallel
 * programs. 
 */
int i, j;
int num_vwgt;
int num_ewgt;
float *sum;
char *yo = "Zoltan_HG_Print";

  if (hg == NULL)
    return;

  ZOLTAN_TRACE_ENTER(zz, yo);

  num_vwgt = hg->VtxWeightDim;
  num_ewgt = hg->EdgeWeightDim;

  sum = (float *) ZOLTAN_MALLOC(MAX(num_vwgt, num_ewgt) * sizeof(float));

  fprintf(fp, "%s nVtx=%d nEdge=%d nPins=%d vWgt=%d eWgt=%d\n", 
          str, hg->nVtx, hg->nEdge, hg->nPins, 
          hg->VtxWeightDim, hg->EdgeWeightDim);

  /* Print Vertex Info */
  fprintf(fp, "%s Vertices:  (edges)\n", str);
  for (i = 0; i < hg->nVtx; i++) {
    fprintf(fp, "%d (%d) in part %d:  ", 
            i, VTX_LNO_TO_GNO(hg, i), (parts ? parts[i] : -1));
    fprintf(fp, "(");
    for (j = hg->vindex[i]; j < hg->vindex[i+1]; j++)
      fprintf(fp, "%d ", hg->vedge[j]);
    fprintf(fp, ")\n");
  }

  if (hg->vwgt != NULL) {
    for (j = 0; j < num_vwgt; j++) sum[j] = 0;
    fprintf(fp, "%s Vertices: [weights])\n", str);
    for (i = 0; i < hg->nVtx; i++) {
      fprintf(fp, "%d (%d):  [", i, VTX_LNO_TO_GNO(hg, i));
      for (j = 0; j < num_vwgt; j++) {
        fprintf(fp, "%f ", hg->vwgt[i*num_vwgt + j]);
        sum[j] += hg->vwgt[i*num_vwgt + j];
      }
      fprintf(fp, "])\n");
    }
    fprintf(fp, "Total vertex weight = [");
    for (j = 0; j < num_vwgt; j++) fprintf(fp, "%f  ", sum[j]);
    fprintf(fp, "]\n");
  }

  /* Print Hyperedge Info */
  fprintf(fp, "%s Hyperedges:  (vertices)\n", str);
  for (i = 0; i < hg->nEdge; i++) {
    fprintf(fp, "%d (%d):  ", i, EDGE_LNO_TO_GNO(hg, i));
    fprintf(fp, "(");
    for (j = hg->hindex[i]; j < hg->hindex[i+1]; j++)
      fprintf(fp, "%d ", hg->hvertex[j]);
    fprintf(fp, ")\n");
  }

  if (hg->ewgt != NULL) {
    for (j = 0; j < num_ewgt; j++) sum[j] = 0;
    fprintf(fp, "%s Hyperedge Weights:  [weights]\n", str);
    for (i = 0; i < hg->nEdge; i++) {
      fprintf(fp, "%d (%d):  ", i, EDGE_LNO_TO_GNO(hg, i));
      fprintf(fp, "[");
      for (j = 0; j < num_ewgt; j++) {
        fprintf(fp, "%f ", hg->ewgt[i*num_ewgt + j]);
        sum[j] += hg->ewgt[i*num_ewgt + j];
      }
      fprintf(fp, "])\n");
    }
    fprintf(fp, "Total hyperedge weight = [");
    for (j = 0; j < num_ewgt; j++) fprintf(fp, "%f  ", sum[j]);
    fprintf(fp, "]\n");
  }

  ZOLTAN_FREE(&sum);
  ZOLTAN_TRACE_EXIT(zz, yo);
}
Beispiel #4
0
void Zoltan_PHG_Plot_2D_Distrib(
  ZZ *zz,
  HGraph *phg
)
{
/* Routine that produces gnuplot output of 2D data distribution in form of 
 * a matrix.
 * One column for each vertex.
 * One row for each hyperedge.
 * Separate files are produced for each processor.
 * Vertex and edge global node numbers are used for "coordinates" in plotting.
 * No partitioning information is displayed; only the 2D data distribution 
 * is shown.
 */
static int cnt = 0;
char filename[32];
FILE *fp = NULL;
int i, j;
int egno, vgno;

  sprintf(filename, "phg%02d.%02d", cnt, zz->Proc);
  fp = fopen(filename, "w");

  for (i = 0; i < phg->nEdge; i++) {
    egno = EDGE_LNO_TO_GNO(phg, i);
    for (j = phg->hindex[i]; j < phg->hindex[i+1]; j++) {
      vgno = VTX_LNO_TO_GNO(phg, phg->hvertex[j]);
      fprintf(fp, "%d  %d\n", vgno, -egno);
    }
  }
  fclose(fp);
  if (zz->Proc == 0) {
    sprintf(filename, "phg%02d.gnuload", cnt);
    fp = fopen(filename, "w");
    fprintf(fp, "set data style points\n");
    fprintf(fp, "set pointsize 5\n");
    fprintf(fp, "set nokey\n");
    fprintf(fp, "set xlabel \"vertices\"\n");
    fprintf(fp, "set ylabel \"-hyperedges\"\n");
    fprintf(fp, "plot ");
    for (i = 0; i < zz->Num_Proc; i++) {
      fprintf(fp, "\"phg%02d.%02d\"", cnt, i);
      if (i != zz->Num_Proc-1)
        fprintf(fp, ", ");
      else
        fprintf(fp, "\n");
    }
    fclose(fp);
  }

  /* Sanity check to ensure Mirror is working correctly */
  /* Don't need to generate both sets of files, but they should differ only 
   * in the order of the points */
  sprintf(filename, "phgmirror%02d.%02d", cnt, zz->Proc);
  fp = fopen(filename, "w");

  for (i = 0; i < phg->nVtx; i++) {
    vgno = VTX_LNO_TO_GNO(phg, i);
    for (j = phg->vindex[i]; j < phg->vindex[i+1]; j++) {
      egno = EDGE_LNO_TO_GNO(phg, phg->vedge[j]);
      fprintf(fp, "%d  %d\n", vgno, -egno);
    }
  }
  fclose(fp);
  if (zz->Proc == 0) {
    sprintf(filename, "phgmirror%02d.gnuload", cnt);
    fp = fopen(filename, "w");
    fprintf(fp, "set data style points\n");
    fprintf(fp, "set pointsize 5\n");
    fprintf(fp, "set nokey\n");
    fprintf(fp, "set xlabel \"vertices\"\n");
    fprintf(fp, "set ylabel \"-hyperedges\"\n");
    fprintf(fp, "plot ");
    for (i = 0; i < zz->Num_Proc; i++) {
      fprintf(fp, "\"phgmirror%02d.%02d\"", cnt, i);
      if (i != zz->Num_Proc-1)
        fprintf(fp, ", ");
      else
        fprintf(fp, "\n");
    }
    fclose(fp);
  }

  cnt++;
}