Actual source code: jostle.c

  1: #define PETSCMAT_DLL

 3:  #include ../src/mat/impls/adj/mpi/mpiadj.h

  5: #ifdef PETSC_HAVE_UNISTD_H
  6: #include <unistd.h>
  7: #endif

  9: #ifdef PETSC_HAVE_STDLIB_H
 10: #include <stdlib.h>
 11: #endif

 13: #include "petscfix.h"


 17: #include "jostle.h"
 18: /* this function is not declared in 'jostle.h' */


 23: typedef struct {
 24:     int output;
 25:     int coarse_seq;
 26:     int nbvtxcoarsed;           /* number of vertices for the coarse graph */
 27:     char *mesg_log;
 28: } MatPartitioning_Jostle;

 30: #define SIZE_LOG 10000          /* size of buffer for msg_log */

 34: static PetscErrorCode MatPartitioningApply_Jostle(MatPartitioning part, IS * partitioning)
 35: {
 37:     int  size, rank, i;
 38:     Mat mat = part->adj, matMPI;
 39:     Mat_MPIAdj *adj = (Mat_MPIAdj *) mat->data;
 40:     MatPartitioning_Jostle *jostle_struct = (MatPartitioning_Jostle *) part->data;
 41:     PetscTruth flg;
 42: #ifdef PETSC_HAVE_UNISTD_H
 43:     int fd_stdout, fd_pipe[2], count,err;
 44: #endif


 48:     /* check that the number of partitions is equal to the number of processors */
 49:     MPI_Comm_rank(((PetscObject)mat)->comm, &rank);
 50:     MPI_Comm_size(((PetscObject)mat)->comm, &size);
 51:     if (part->n != size) SETERRQ(PETSC_ERR_SUP, "Supports exactly one domain per processor");

 53:     /* convert adjacency matrix to MPIAdj if needed*/
 54:     PetscTypeCompare((PetscObject) mat, MATMPIADJ, &flg);
 55:     if (!flg) {
 56:         MatConvert(mat, MATMPIADJ, MAT_INITIAL_MATRIX, &matMPI);
 57:     } else {
 58:         matMPI = mat;
 59:     }

 61:     adj = (Mat_MPIAdj *) matMPI->data;  /* adj contains adjacency graph */
 62:     {
 63:         /* definition of Jostle library arguments */
 64:         int nnodes = matMPI->M; /* number of vertices in full graph */
 65:         int offset = 0;         /* 0 for C array indexing */
 66:         int core = matMPI->m;
 67:         int halo = 0;           /* obsolete with contiguous format */
 68:         int *index_jostle;      /* contribution of each processor */
 69:         int nparts = part->n;
 70:         int *part_wt = NULL;

 72:         int *partition;         /* set number of each vtx (length n) */
 73:         int *degree;            /* degree for each core nodes */
 74:         int *edges = adj->j;
 75:         int *node_wt = NULL;    /* nodes weights */
 76:         int *edge_wt = NULL;    /* edges weights */
 77:         double *coords = NULL;  /* not used (cf jostle documentation) */

 79:         int local_nedges = adj->nz;
 80:         int dimension = 0;      /* not used */
 81:         int output_level = jostle_struct->output;
 82:         char env_str[256];

 84:         /* allocate index_jostle */
 85:         PetscMalloc(nparts * sizeof(int), &index_jostle);

 87:         /* compute number of core nodes for each one */
 88:         for (i = 0; i < nparts - 1; i++)
 89:             index_jostle[i] = adj->rowners[i + 1] - adj->rowners[i];
 90:         index_jostle[nparts - 1] = nnodes - adj->rowners[nparts - 1];

 92:         /* allocate the partition vector */
 93:         PetscMalloc(core * sizeof(int), &partition);

 95:         /* build the degree vector and the local_nedges value */
 96:         PetscMalloc(core * sizeof(int), &degree);
 97:         for (i = 0; i < core; i++)
 98:             degree[i] = adj->i[i + 1] - adj->i[i];

100:         /* library call */
101:         pjostle_init(&size, &rank);
102:         pjostle_comm(&((PetscObject)matMPI)->comm);
103:         jostle_env("format = contiguous");
104:         jostle_env("timer = off");

106:         sprintf(env_str, "threshold = %d", jostle_struct->nbvtxcoarsed);
107:         jostle_env(env_str);

109:         if (jostle_struct->coarse_seq)
110:           jostle_env("matching = local");

112:         /* redirect output */
113: #ifdef PETSC_HAVE_UNISTD_H
114:         fd_stdout = dup(1);
115:         pipe(fd_pipe);
116:         close(1);
117:         dup2(fd_pipe[1], 1);
118: #endif

120:         pjostle(&nnodes, &offset, &core, &halo, index_jostle, degree, node_wt,
121:             partition, &local_nedges, edges, edge_wt, &nparts,
122:             part_wt, &output_level, &dimension, coords);

124:         printf("Jostle Partitioner statistics\ncut : %d, balance : %f, runtime : %f, mem used : %d\n",
125:             jostle_cut(), jostle_bal(), jostle_tim(), jostle_mem());

127: #ifdef PETSC_HAVE_UNISTD_H
128:         PetscMalloc(SIZE_LOG * sizeof(char), &(jostle_struct->mesg_log));
129:         err = fflush(stdout);
130:         if (err) SETERRQ(PETSC_ERR_SYS,"fflush() failed on stdout");
131:         count = read(fd_pipe[0], jostle_struct->mesg_log, (SIZE_LOG - 1) * sizeof(char));
132:         if (count < 0)
133:             count = 0;
134:         jostle_struct->mesg_log[count] = 0;
135:         close(1);
136:         dup2(fd_stdout, 1);
137:         close(fd_stdout);
138:         close(fd_pipe[0]);
139:         close(fd_pipe[1]);
140: #endif

142:         /* We free the memory used by jostle */
143:         PetscFree(index_jostle);
144:         PetscFree(degree);

146:         /* Creation of the index set */
147:         ISCreateGeneral(((PetscObject)part)->comm, mat->m, partition, partitioning);

149:         if (matMPI != mat) {
150:             MatDestroy(matMPI);
151:         }

153:         PetscFree(partition);
154:     }

156:     return(0);
157: }


162: PetscErrorCode MatPartitioningView_Jostle(MatPartitioning part, PetscViewer viewer)
163: {
164:   MatPartitioning_Jostle *jostle_struct = (MatPartitioning_Jostle *) part->data;
165:   PetscErrorCode         ierr;
166:   PetscTruth             iascii;

169:   PetscTypeCompare((PetscObject) viewer, PETSC_VIEWER_ASCII, &iascii);
170:   if (iascii) {
171:     if (jostle_struct->mesg_log) {
172:       PetscViewerASCIIPrintf(viewer, "%s\n", jostle_struct->mesg_log);
173:     }
174:   } else {
175:     SETERRQ1(PETSC_ERR_SUP, "Viewer type %s not supported for this Jostle partitioner",((PetscObject)viewer)->type_name);
176:   }
177:   return(0);
178: }

182: /*@
183:     MatPartitioningJostleSetCoarseLevel - Set the coarse level 
184:     
185:   Input Parameter:
186: .  part - the partitioning context
187: .  level - the coarse level in range [0.0,1.0]

189:    Level: advanced

191: @*/
192: PetscErrorCode  MatPartitioningJostleSetCoarseLevel(MatPartitioning part, PetscReal level)
193: {
194:     MatPartitioning_Jostle *jostle_struct = (MatPartitioning_Jostle *) part->data;


198:     if (level < 0.0 || level > 1.0) {
199:         SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,
200:             "Jostle: level of coarsening out of range [0.0-1.0]");
201:     } else
202:         jostle_struct->nbvtxcoarsed = (int)(part->adj->N * level);

204:     if (jostle_struct->nbvtxcoarsed < 20)
205:         jostle_struct->nbvtxcoarsed = 20;

207:     return(0);
208: }

212: /*@
213:      MatPartitioningJostleSetCoarseSequential - Use the sequential code to 
214:          do the partitioning of the coarse grid.

216:   Input Parameter:
217: .  part - the partitioning context

219:    Level: advanced

221: @*/
222: PetscErrorCode  MatPartitioningJostleSetCoarseSequential(MatPartitioning part)
223: {
224:     MatPartitioning_Jostle *jostle_struct =
225:         (MatPartitioning_Jostle *) part->data;
227:     jostle_struct->coarse_seq = 1;
228:     return(0);
229: }

233: PetscErrorCode MatPartitioningSetFromOptions_Jostle(MatPartitioning part)
234: {
236:     PetscTruth flag;
237:     PetscReal level;

240:     PetscOptionsHead("Set Jostle partitioning options");

242:     PetscOptionsReal("-mat_partitioning_jostle_coarse_level",
243:         "Coarse level", "MatPartitioningJostleSetCoarseLevel", 0,
244:         &level, &flag);
245:     if (flag)
246:         MatPartitioningJostleSetCoarseLevel(part, level);

248:     PetscOptionsName("-mat_partitioning_jostle_coarse_sequential",
249:         "Use sequential coarse partitioner",
250:         "MatPartitioningJostleSetCoarseSequential", &flag);
251:     if (flag) {
252:         MatPartitioningJostleSetCoarseSequential(part);
253:     }

255:     PetscOptionsTail();
256:     return(0);
257: }


262: PetscErrorCode MatPartitioningDestroy_Jostle(MatPartitioning part)
263: {
264:     MatPartitioning_Jostle *jostle_struct = (MatPartitioning_Jostle *) part->data;
265:     PetscErrorCode         ierr;

268:     PetscFree(jostle_struct->mesg_log);
269:     PetscFree(jostle_struct);
270:     return(0);
271: }

273: /*MC
274:    MAT_PARTITIONING_JOSTLE - Creates a partitioning context via the external package Jostle.

276:    Collective on MPI_Comm

278:    Input Parameter:
279: .  part - the partitioning context

281:    Options Database Keys:
282: +  -mat_partitioning_jostle_coarse_level <0>: Coarse level (MatPartitioningJostleSetCoarseLevel)
283: -  -mat_partitioning_jostle_coarse_sequential: Use sequential coarse partitioner (MatPartitioningJostleSetCoarseSequential)

285:    Level: beginner

287:    Notes: See http://www.gre.ac.uk/~c.walshaw/jostle/

289: .keywords: Partitioning, create, context

291: .seealso: MatPartitioningSetType(), MatPartitioningType

293: M*/

298: PetscErrorCode  MatPartitioningCreate_Jostle(MatPartitioning part)
299: {
301:     MatPartitioning_Jostle *jostle_struct;

304:     PetscNewLog(part,MatPartitioning_Jostle, &jostle_struct);
305:     part->data = (void*) jostle_struct;

307:     jostle_struct->nbvtxcoarsed = 20;
308:     jostle_struct->output = 0;
309:     jostle_struct->coarse_seq = 0;
310:     jostle_struct->mesg_log = NULL;

312:     part->ops->apply = MatPartitioningApply_Jostle;
313:     part->ops->view = MatPartitioningView_Jostle;
314:     part->ops->destroy = MatPartitioningDestroy_Jostle;
315:     part->ops->setfromoptions = MatPartitioningSetFromOptions_Jostle;

317:     return(0);
318: }