int Zoltan_LB_Point_Assign ( ZZ *zz, double *x, int *proc) { /* Returns processor to which a point should be assigned. */ char *yo = "Zoltan_LB_Point_Assign"; if (zz->LB.Point_Assign == NULL) { /* function not supported by current decomposition method */ ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Point_Assign not supported by chosen partitioning method."); return ZOLTAN_FATAL; } if (zz->LB.PartDist != NULL) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Non-uniform distribution of partitions over processors is specified; " "use Zoltan_LB_Point_PP_Assign."); return ZOLTAN_FATAL; } /* call appropriate method; pass proc in partition argument for greater * efficiency within LB.Point_Assign (Zoltan is partition-based). */ return zz->LB.Point_Assign(zz, x, NULL, proc); }
/* * Compute an array that contains the cumulative sum of objects * on each processor. * * Memory for the vtxdist array is allocated here, * but must be freed by the calling routine. * */ int Zoltan_Get_Distribution(ZZ *zz, int **vtxdist) { int ierr = ZOLTAN_OK, num_obj; char *yo = "Zoltan_Get_Distribution"; num_obj = zz->Get_Num_Obj(zz->Get_Num_Obj_Data, &ierr); if (ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN){ /* Return error code */ ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error in Get_Num_Obj."); return (ierr); } *vtxdist = (int *) ZOLTAN_MALLOC((zz->Num_Proc+1)*sizeof(int)); if (num_obj>0){ if (!(*vtxdist)){ /* Not enough memory */ ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Out of memory."); return ZOLTAN_MEMERR; } } /* Construct *vtxdist[i] = the number of objects on all procs < i. */ /* Scan to compute partial sums of the number of objs */ MPI_Scan (&num_obj, *vtxdist, 1, MPI_INT, MPI_SUM, zz->Communicator); /* Gather data from all procs */ MPI_Allgather (&((*vtxdist)[0]), 1, MPI_INT, &((*vtxdist)[1]), 1, MPI_INT, zz->Communicator); (*vtxdist)[0] = 0; return ZOLTAN_OK; }
int Zoltan_LB_Box_Assign ( ZZ *zz, double xlo, double ylo, double zlo, double xhi, double yhi, double zhi, int *procs, int *count) { char *yo = "Zoltan_LB_Box_Assign"; int tmp = 0; if (zz->LB.Box_Assign == NULL) { /* function not supported by current decomposition method */ ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Box_Assign not supported by chosen partitioning method."); return ZOLTAN_FATAL; } if (zz->LB.PartDist != NULL) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Non-uniform distribution of partitions over processors is specified; " "use Zoltan_LB_Box_PP_Assign."); return ZOLTAN_FATAL; } /* Call appropriate method. Pass procs and count in partition arguments * for greater efficiency in LB.Box_Assign (Zoltan is partition-based.) */ return zz->LB.Box_Assign(zz, xlo, ylo, zlo, xhi, yhi, zhi, NULL, &tmp, procs, count); }
int Zoltan_DD_Set_Neighbor_Hash_Fn1 ( Zoltan_DD_Directory *dd, /* directory state information */ int size) /* number of reserved GIDs per CPU */ { char *yo = "Zoltan_DD_Set_Hash_Fn1"; struct dd_nh1_struct *hashdata; if (dd == NULL || size < 1) { ZOLTAN_PRINT_ERROR (0, yo, "Invalid input argument"); return ZOLTAN_FATAL; } hashdata = (struct dd_nh1_struct*) ZOLTAN_MALLOC(sizeof(struct dd_nh1_struct)); if (hashdata == NULL) { ZOLTAN_PRINT_ERROR (0, yo, "Memory error"); return ZOLTAN_FATAL; } hashdata->groupsize = size; dd->hash = (DD_Hash_fn*) &dd_nh1; dd->cleanup = (DD_Cleanup_fn*) &Zoltan_DD_default_cleanup; dd->hashdata = hashdata; hashdata->max_gid = size * dd->nproc; /* larger GIDs out of range */ return ZOLTAN_OK; }
int Zoltan_DD_Set_Neighbor_Hash_Fn3 ( Zoltan_DD_Directory *dd, /* directory state information */ int total) /* total number of GIDS */ { char *yo = "Zoltan_DD_Set_Hash_Fn3"; struct dd_nh3_struct *hashdata; if (dd == NULL || total < 1) { ZOLTAN_PRINT_ERROR (0, yo, "Invalid input argument"); return ZOLTAN_FATAL; } hashdata = (struct dd_nh3_struct*) ZOLTAN_MALLOC(sizeof(struct dd_nh3_struct)); if (hashdata == NULL) { ZOLTAN_PRINT_ERROR (0, yo, "Memory error"); return ZOLTAN_FATAL; } hashdata->total_ = total; hashdata->average = total / dd->nproc; hashdata->remainder = total % dd->nproc; hashdata->breakpt = (hashdata->average+1) * hashdata->remainder; dd->hash = (DD_Hash_fn*) &dd_nh3; dd->hashdata = hashdata; dd->cleanup = (DD_Cleanup_fn*)&Zoltan_DD_default_cleanup; return ZOLTAN_OK; }
/* Routine to set function pointers corresponding to input-string options. */ int Zoltan_PHG_Set_Part_Options (ZZ *zz, PHGPartParams *hgp) { int err; char *yo = "Zoltan_PHG_Set_Part_Options"; if (hgp->bal_tol < 1.0) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Invalid PHG_BALANCE_TOLERANCE."); return ZOLTAN_FATAL; } /* Set coarsening method. */ hgp->matching = NULL; if (!(Zoltan_PHG_Set_Matching_Fn (hgp))) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Invalid PHG_COARSENING_METHOD."); return ZOLTAN_FATAL; } /* Set (serial) coarse partitioning method. NOTE: May need parallel * partitioning method later if reduction to 1 proc fails */ hgp->CoarsePartition = Zoltan_PHG_Set_CoarsePartition_Fn(hgp, &err); if (err != ZOLTAN_OK) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Invalid PHG_COARSEPARTITION_METHOD."); return ZOLTAN_FATAL; } /* Set refinement method. */ if (!(hgp->Refinement = Zoltan_PHG_Set_Refinement_Fn(hgp->refinement_str))) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Invalid PHG_REFINEMENT_METHOD."); return ZOLTAN_FATAL; } return ZOLTAN_OK; }
static int coarse_part_greedy ( ZZ *zz, HGraph *hg, int p, float *part_sizes, Partition part, PHGPartParams *hgp ) { int start; #if 0 /* UVC commented out to avoid warning */ int scaling; float *new_ewgt=NULL; #endif float *old_ewgt=NULL; int err = ZOLTAN_OK; char *yo = "coarse_part_greedy"; if (hg->nVtx == 0) return ZOLTAN_OK; /* Nothing to do. */ #if 0 /* Disable edge scaling for now since collective comm causes hang. TODO */ /* Scale the edge weights */ if (hg->nEdge) { if (!(new_ewgt = (float*) ZOLTAN_MALLOC(hg->nEdge * sizeof(float)))) ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Out of memory") else { if (hgp->edge_scaling) scaling = hgp->edge_scaling; else /* Pick a random scaling. */ scaling = Zoltan_Rand(NULL) % 4; /* scaling is in [0,3] */ /* Temporarily scale the edge weights (save old weights) */ Zoltan_PHG_Scale_Edges (zz, hg, new_ewgt, scaling); old_ewgt = hg->ewgt; hg->ewgt = new_ewgt; } } #endif /* Start at random vertex */ start = Zoltan_Rand(NULL) % (hg->nVtx); if (p==2) /* Call greedy method. */ err = greedy_grow_part(zz, hg, start, p, part_sizes, part, hgp); else /* We should always do bisection?? */ ZOLTAN_PRINT_ERROR (zz->Proc, yo, "Invalid value for p, expected p=2."); /* Restore original edge weights */ if (old_ewgt){ ZOLTAN_FREE(&(hg->ewgt)); hg->ewgt = old_ewgt; old_ewgt = NULL; } return err; }
/* * gather_by_list * input: a list of processors, a message to be sent to these processors, * and a receive buffer to get data back. * * output: concatenated messages from other processors in rbuff, with * appropriate size info in rbuff_size. */ int gather_by_list(int procs_length, int *procs, int sbuff_size, char *sbuff, int *rbuff_size, char **rbuff, MPI_Comm *comm) { int i, receive_size, mtag, err, myProc; char *send; ZOLTAN_COMM_OBJ *plan; static char *yo = "gather_by_list"; MPI_Comm_rank(*comm, &myProc); if (!(send = (char*) ZOLTAN_MALLOC(procs_length * sizeof(int)))) { ZOLTAN_PRINT_ERROR(myProc, yo, "Insufficient memory"); return ZOLTAN_MEMERR; } mtag = 0; for (i = 0; i < procs_length; ++i) ((int*)send)[i] = sbuff_size; /* create and resize communication plan */ err = Zoltan_Comm_Create(&plan, procs_length, procs, *comm, mtag++, &receive_size); if (err < 0) ZOLTAN_PRINT_ERROR(myProc, yo, "Zoltan_Comm_Create failed."); err = Zoltan_Comm_Resize(plan, (int*)send, mtag++, rbuff_size); if (err < 0) ZOLTAN_PRINT_ERROR(myProc, yo, "Zoltan_Comm_Resize failed."); ZOLTAN_FREE(&send); /* allocate send and receive buffer */ if ((!(*rbuff = (char*) ZOLTAN_MALLOC(*rbuff_size)) && (*rbuff_size != 0)) ||!( send = (char*) ZOLTAN_MALLOC(sbuff_size * procs_length))) { printf("failed allocating %d + %d * %d bytes. . .", *rbuff_size, sbuff_size, procs_length); fflush(NULL); ZOLTAN_PRINT_ERROR(myProc, yo, "Insufficient Memory"); return ZOLTAN_MEMERR; } /* copy message for each processor */ for (i = 0; i < procs_length; ++i) memcpy(send + i * sbuff_size, sbuff, sbuff_size); /* finally, we can do the communication */ err = Zoltan_Comm_Do(plan, mtag++, send, 1, *rbuff); if (err < 0) ZOLTAN_PRINT_ERROR(myProc, yo, "Zoltan_Comm_Do failed."); /* clean up */ Zoltan_Comm_Destroy(&plan); ZOLTAN_FREE(&send); return err; }
static int check_input( ZZ *zz, int parts, int *include_parts ) { /* * Routine to ensure that all processors have the same values of * zz->Num_GID and zz->Num_LID. * Also, check whether partitions are included on any processors; if so, * set include_parts to true. * All processors return the same error code. */ char *yo = "check_input"; char msg[256]; int loc_tmp[6]; int glob[] = {0, 0, 0, 0, 0, 0}; int ierr = ZOLTAN_OK; loc_tmp[0] = zz->Num_GID; loc_tmp[1] = zz->Num_LID; loc_tmp[2] = parts; loc_tmp[3] = -(zz->Num_GID); loc_tmp[4] = -(zz->Num_LID); loc_tmp[5] = -(parts); /* * Check both max and min values of IDs so that all processors can * return the same error code. */ MPI_Allreduce(loc_tmp, glob, 6, MPI_INT, MPI_MIN, zz->Communicator); *include_parts = -(glob[5]); if ((glob[0] != -(glob[3])) || (glob[1] != -(glob[4]))) ierr = ZOLTAN_FATAL; if (zz->Num_GID != -(glob[3])) { sprintf(msg, "Inconsistent global id sizes: Num_GID = %d " "but global max is %d\n", zz->Num_GID, -(glob[3])); ZOLTAN_PRINT_ERROR(zz->Proc, yo, msg); } if (zz->Num_LID != -(glob[4])) { sprintf(msg, "Inconsistent local id sizes: Num_LID = %d " "but global max is %d\n", zz->Num_LID, -(glob[4])); ZOLTAN_PRINT_ERROR(zz->Proc, yo, msg); } return ierr; }
int Zoltan_Help_Migrate( ZZ *zz, int num_import, ZOLTAN_ID_PTR import_global_ids, ZOLTAN_ID_PTR import_local_ids, int *import_procs, int num_export, ZOLTAN_ID_PTR export_global_ids, ZOLTAN_ID_PTR export_local_ids, int *export_procs ) { /* * Wrapper around Zoltan_Migrate with NULL pointers for partition arrays. * Maintained for backward compatibility. * Arguments are same as for Zoltan_Migrate. */ char *yo = "Zoltan_Help_Migrate"; int ierr; ZOLTAN_TRACE_ENTER(zz, yo); if (zz->LB.PartDist != NULL) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Non-uniform distribution of partitions over processors is specified; " "use Zoltan_Migrate\n"); ierr = ZOLTAN_FATAL; goto End; } if (zz->Migrate.Pre_Migrate_PP || zz->Migrate.Mid_Migrate_PP || zz->Migrate.Post_Migrate_PP) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Partition information not available in Zoltan_Help_Migrate for " "ZOLTAN_*_MIGRATE_PP_FNs; use ZOLTAN_*_MIGRATE_FNs instead."); ierr = ZOLTAN_FATAL; goto End; } /* * Wrapper (for backward compatilibity) around Zoltan_Migrate. * Passes NULL for partition assignment arrays. */ ierr = Zoltan_Migrate(zz, num_import, import_global_ids, import_local_ids, import_procs, NULL, num_export, export_global_ids, export_local_ids, export_procs, NULL); End: ZOLTAN_TRACE_EXIT(zz, yo); return ierr; }
int Zoltan_DD_Set_Neighbor_Hash_Fn2 ( Zoltan_DD_Directory *dd, /* directory state information */ int *proc, /* list of processors for following info */ int *low, /* lowest GID for corresponding processor */ int *high, /* highest GID for corresponding processor */ int n) /* number of processors in above lists */ { int i; char *yo = "Zoltan_DD_Set_Hash_Fn2"; struct dd_nh2_struct *hashdata; if (dd == NULL || proc == NULL || low == NULL || high == NULL) { ZOLTAN_PRINT_ERROR (0, yo, "Invalid input argument"); return ZOLTAN_FATAL; } hashdata = (struct dd_nh2_struct*) ZOLTAN_MALLOC(sizeof(struct dd_nh2_struct)); if (hashdata == NULL) { ZOLTAN_PRINT_ERROR (0, yo, "Memory error"); return ZOLTAN_FATAL; } /* register functions for automatic invocation */ dd->hash = (DD_Hash_fn*) &dd_nh2; dd->cleanup = (DD_Cleanup_fn*)&dd_nh2_cleanup; dd->hashdata = hashdata; /* malloc and initialize storage for range information structures */ hashdata->ptr = (Range_Info*) ZOLTAN_MALLOC (n * sizeof (Range_Info)); if (hashdata->ptr == NULL) { ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to Malloc range info"); return ZOLTAN_MEMERR; } for (i = 0; i < n; i++) { hashdata->ptr[i].high = high[i] ; hashdata->ptr[i].low = low [i] ; hashdata->ptr[i].proc = (proc[i] < n) ? proc[i] : 0; } /* do not assume user lists were ordered */ qsort (hashdata->ptr, n, sizeof (Range_Info), compare_sort); hashdata->low_limit = hashdata->ptr[0].low; hashdata->high_limit = hashdata->ptr[n-1].high; hashdata->debug_level = dd->debug_level; hashdata->count = n; hashdata->nproc = dd->nproc; return ZOLTAN_OK; }
double Zoltan_PHG_Compute_Balance ( ZZ *zz, HGraph *hg, float *part_sizes, int wgtidx,/* compute balance w.r.t. this component of vwgt and part_sizes */ int p, Partition part ) { int i; double *lsize_w, *size_w, max_imbal, tot_w; char *yo = "Zoltan_PHG_Compute_Balance"; int part_dim = (hg->VtxWeightDim ? hg->VtxWeightDim : 1); if (!hg || !hg->comm || !hg->comm->row_comm) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Unable to compute balance"); return 1.0; } if (!(lsize_w = (double*) ZOLTAN_CALLOC (2*p, sizeof(double)))) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Insufficient memory."); return ZOLTAN_MEMERR; } size_w = lsize_w + p; if (hg->vwgt) for (i = 0; i < hg->nVtx; i++) lsize_w[part[i]] += hg->vwgt[i*hg->VtxWeightDim+wgtidx]; else for (i = 0; i < hg->nVtx; i++) lsize_w[part[i]]++; MPI_Allreduce(lsize_w, size_w, p, MPI_DOUBLE, MPI_SUM, hg->comm->row_comm); max_imbal = tot_w = 0.0; for (i = 0; i < p; i++) tot_w += size_w[i]; if (tot_w) { for (i = 0; i < p; i++) { float this_part_size = part_sizes[i*part_dim+wgtidx]; if (this_part_size) { double ib=(size_w[i]-this_part_size*tot_w)/(this_part_size*tot_w); if (ib>max_imbal) max_imbal = ib; } } } ZOLTAN_FREE (&lsize_w); return 1.0+max_imbal; }
int Zoltan_Map_First(ZZ *zz, ZOLTAN_MAP* map, int **key, int *data) { char *yo = "Zoltan_Map_First"; ZOLTAN_ENTRY *entry = NULL; int i; *key = NULL; *data = ZOLTAN_NOT_FOUND; if (map){ if (map->entry_count == 0){ map->prev_index = -1; map->prev_hash_index = -1; map->prev = NULL; } else{ if (!map->dynamicEntries){ map->prev_index = 0; entry = map->top; } else{ /* find the first entry in the map */ for (i=0; i <= map->max_index; i++){ if (map->entries[i]){ map->prev_hash_index = i; entry = map->prev = map->entries[i]; break; } } if (!entry){ ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Entry not found\n"); return ZOLTAN_FATAL; } } *key = entry->key; *data = entry->data; } } else { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Invalid map\n"); return ZOLTAN_FATAL; } return ZOLTAN_OK; }
int Zoltan_Map_Find(ZZ *zz, ZOLTAN_MAP* map, int *key, int *data) { char *yo = "Zoltan_Map_Find"; int index, match; ZOLTAN_ENTRY *element; ZOLTAN_ID_PTR zkey = (ZOLTAN_ID_PTR)key; *data = ZOLTAN_NOT_FOUND; if (!map){ ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Map specified does not exist\n"); return ZOLTAN_FATAL; } index = Zoltan_Hash(zkey, map->id_size, map->max_index); element = map->entries[index]; match = 0; while (element != NULL){ match = key_match(map->id_size, element->key, key); if (match){ *data = element->data; break; } element = element->next; } return ZOLTAN_OK; }
int Zoltan_KVHash_Insert(KVHash *hash, ZOLTAN_GNO_TYPE key, int value) { int i; G2LHashNode *ptr; i = Zoltan_Hash((ZOLTAN_ID_PTR) (void *)&key, hash->num_gid_entries, (unsigned int) hash->maxsize); for (ptr=hash->table[i]; ptr && ptr->gno!=key; ptr = ptr->next); if (!ptr) { if (hash->size >= hash->maxsize) { ZOLTAN_PRINT_ERROR(-1, "Zoltan_KVHash_Insert", "Hash is full!"); return -1; } ptr = &(hash->nodes[hash->size]); ptr->gno = key; ptr->lno = value; ptr->next = hash->table[i]; hash->table[i] = ptr; ++hash->size; } else value = ptr->lno; return value; }
int Zoltan_G2LHash_Insert(G2LHash *hash, ZOLTAN_GNO_TYPE gno) { int i, lno; G2LHashNode *ptr; if (gno<hash->base || gno>hash->baseend) { i = Zoltan_Hash((ZOLTAN_ID_PTR) (void *)&gno, hash->num_gid_entries, (unsigned int) hash->maxsize); for (ptr=hash->table[i]; ptr && ptr->gno!=gno; ptr = ptr->next); if (!ptr) { if (hash->size >= hash->maxsize) { char st[2048]; sprintf(st, "Hash is full! #entries=%d maxsize=%d", hash->size, hash->maxsize); ZOLTAN_PRINT_ERROR(-1, "Zoltan_G2LHash_G2L", st); return -1; } ptr = &(hash->nodes[hash->size]); ptr->gno = gno; lno = ptr->lno = hash->nlvtx + hash->size; ptr->next = hash->table[i]; hash->table[i] = ptr; ++hash->size; } else lno = ptr->lno; } else return gno-hash->base; return lno; }
/* Random partitioning. Sequence partitioning with vertices in random order. */ static int coarse_part_random ( ZZ *zz, HGraph *hg, int p, float *part_sizes, Partition part, PHGPartParams *hgp ) { int i, err=0, *order=NULL; char *yo = "coarse_part_random"; if (!(order = (int*) ZOLTAN_MALLOC (hg->nVtx*sizeof(int)))) { ZOLTAN_FREE (&order); ZOLTAN_PRINT_ERROR (zz->Proc, yo, "Insufficient memory."); return ZOLTAN_MEMERR; } for (i=0; i<hg->nVtx; i++) { order[i] = i; } /* Randomly permute order array */ Zoltan_Rand_Perm_Int (order, hg->nVtx, NULL); /* Call sequence partitioning with random order array. */ err = seq_part (zz, hg, order, p, part_sizes, part, hgp); ZOLTAN_FREE (&order); return err; }
int Zoltan_RCB_Copy_Structure(ZZ *toZZ, ZZ const *fromZZ) { char *yo = "Zoltan_RCB_Copy_Structure"; RCB_STRUCT *to; RCB_STRUCT const *from; from = (RCB_STRUCT const *)fromZZ->LB.Data_Structure; Zoltan_RCB_Free_Structure(toZZ); if (!from){ return(ZOLTAN_OK); } to = (RCB_STRUCT *)ZOLTAN_MALLOC(sizeof(RCB_STRUCT)); if (to == NULL) { ZOLTAN_PRINT_ERROR(fromZZ->Proc, yo, "Insufficient memory."); return(ZOLTAN_MEMERR); } toZZ->LB.Data_Structure = (void *)to; *to = *from; COPY_BUFFER(Tree_Ptr, struct rcb_tree, fromZZ->LB.Num_Global_Parts); COPY_BUFFER(Box, struct rcb_box, 1); return ZOLTAN_OK; }
int Zoltan_LB_Box_PP_Assign ( ZZ *zz, double xlo, double ylo, double zlo, double xhi, double yhi, double zhi, int *procs, int *proc_count, int *parts, int *part_count) { char *yo = "Zoltan_LB_Box_PP_Assign"; if (zz->LB.Box_Assign == NULL) { /* function not supported by current decomposition method */ ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Box_Assign not supported by chosen partitioning method."); return ZOLTAN_FATAL; } /* Call appropriate method. Pass procs and count in partition arguments * for greater efficiency in LB.Box_Assign (Zoltan is partition-based.) */ return zz->LB.Box_Assign(zz, xlo, ylo, zlo, xhi, yhi, zhi, procs, proc_count, parts, part_count); }
int phg_map_GIDs_to_processes(ZZ *zz, ZOLTAN_ID_PTR eid, int size, int lenGID, int **hashedProc, int nprocs) { int i, j; int *procList; static char *yo = "map_GIDs_to_processes"; *hashedProc = NULL; if (size < 1){ return ZOLTAN_OK; } procList = (int *)ZOLTAN_MALLOC(sizeof(int) * size); if (!procList){ ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Memory error."); return ZOLTAN_MEMERR; } for (i=0; i<size; i++){ j = Zoltan_Hash(eid, lenGID, nprocs); procList[i] = j; eid += lenGID; } *hashedProc = procList; return ZOLTAN_OK; }
ZOLTAN_ID_PTR ZOLTAN_Malloc_ID(int n, char *file, int line) { /* * Allocates an array of size n of ZOLTAN_ID_TYPEs and initializes them. */ ZOLTAN_ID_PTR tmp; char *yo = "ZOLTAN_Malloc_ID"; /* * Don't use ZOLTAN_MALLOC macro here; prefer to pass file and line * where ZOLTAN_Malloc_ID was called. */ tmp = (ZOLTAN_ID_PTR) Zoltan_Malloc(n * sizeof(ZOLTAN_ID_TYPE), file, line); if (tmp != NULL) { ZOLTAN_INIT_ID(n,tmp); } else if (n > 0) { char msg[256]; sprintf(msg, "NULL pointer returned; malloc called from %s, line %d.", file, line); ZOLTAN_PRINT_ERROR(-1, yo, msg); } return tmp; }
/* * void Zoltan_Oct_addRegion(pOctant octant, pRegion region) * add a region to oct's list */ int Zoltan_Oct_addRegion(ZZ *zz, pOctant oct, pRegion region) { char *yo = "Zoltan_Oct_addRegion"; pRegion entry; /* pointer to new entry in region list */ if(oct == NULL) return ZOLTAN_WARN; entry = (pRegion) ZOLTAN_MALLOC(sizeof(Region)); /* malloc space for region */ if(entry == NULL) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Cannot allocated memory for region."); return ZOLTAN_MEMERR; } entry->Global_ID = ZOLTAN_MALLOC_GID(zz); entry->Local_ID = ZOLTAN_MALLOC_LID(zz); /* copy region information into the entry */ vector_set(entry->Coord, region->Coord); entry->Weight = region->Weight; ZOLTAN_SET_GID(zz, entry->Global_ID, region->Global_ID); ZOLTAN_SET_LID(zz, entry->Local_ID, region->Local_ID); entry->Proc = region->Proc; /* attach region to region list */ entry->next = oct->list; oct->list = entry; return ZOLTAN_OK; }
/* * gather_row * input: our processor location, a message, and space to hold a return * message. * output: received messages from each processor in our row in rbuff. */ int gather_row(int nProc_x, int nProc_y, int myProc_x, int myProc_y, int sbuff_size, char *sbuff, int *rbuff_size, char **rbuff, MPI_Comm *comm) { int i, my_proc, err; int *procs; static char *yo = "gather_row"; /* create list of processors to send to (everyone in our row but us) */ /* this assumes a linear left->right numbering of processors in our grid */ myProc_y *= nProc_x; my_proc = myProc_x + myProc_y; if (!(procs = (int*) ZOLTAN_MALLOC((nProc_x) * sizeof(int)))) { ZOLTAN_PRINT_ERROR(my_proc, yo, "Insufficient memory"); return ZOLTAN_MEMERR; } /* for (i = 0; i < myProc_x; ++i) procs[i] = myProc_y + i; for (i = myProc_x; i < nProc_x - 1; ++i) procs[i] = myProc_y + i + 1; */ /* do self communication */ for (i = 0; i < nProc_x; ++i) procs[i] = myProc_y + i; err = gather_by_list(nProc_x, procs, sbuff_size, sbuff, rbuff_size, rbuff, comm); ZOLTAN_FREE(&procs); return err; }
void Zoltan_DD_Destroy (Zoltan_DD_Directory **dd) { char *yo = "ZOLTAN_DD_Destroy"; /* input sanity check */ if (dd == NULL || *dd == NULL) { ZOLTAN_PRINT_ERROR (0, yo, "Input argument dd is NULL"); return; } if ((*dd)->debug_level > 4) ZOLTAN_TRACE_IN ((*dd)->my_proc, yo, NULL); ZOLTAN_FREE(&((*dd)->nodelist)); ZOLTAN_FREE(&((*dd)->nodedata)); /* execute user registered cleanup function, if needed */ if ((*dd)->cleanup != NULL) (*dd)->cleanup((*dd)->hashdata); MPI_Comm_free (&((*dd)->comm)); /* free MPI Comm, ignore errors */ if ((*dd)->debug_level > 4) ZOLTAN_TRACE_OUT ((*dd)->my_proc, yo, NULL); ZOLTAN_FREE (dd); /* free directory structure */ return; }
static int get_current_part(ZOLTAN_REFTREE *subroot, ZZ *zz, int *ierr) { /* * Function to return the current partition of an object. * If there is no user defined get_partition function, then the returned * value only indicates whether or not the partition number is this * processor's number. */ char *yo = "get_current_part"; int result; *ierr = ZOLTAN_OK; /* if the user registered a partition function, then use it */ if (zz->Get_Part != NULL) { result = zz->Get_Part(zz->Get_Part_Data,zz->Num_GID,zz->Num_LID, subroot->global_id,subroot->local_id, ierr); if (*ierr != ZOLTAN_OK && *ierr != ZOLTAN_WARN) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error returned from ZOLTAN_PART_FN"); } } else if (zz->Get_Part_Multi != NULL) { /* Not the best use of Multi function, but best I can do. KDD */ zz->Get_Part_Multi(zz->Get_Part_Multi_Data, zz->Num_GID,zz->Num_LID,1, subroot->global_id,subroot->local_id, &result,ierr); if (*ierr != ZOLTAN_OK && *ierr != ZOLTAN_WARN) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error returned from ZOLTAN_PART_MULTI_FN"); } } else { /* otherwise, return my processor number if the object is assigned to this processor, or any other value if it is not */ if (subroot->assigned_to_me) result = zz->Proc; else result = zz->Proc-1; } return(result); }
int Zoltan_Heap_Input (HEAP *h, int element, float value) { static char *yo = "Zoltan_Heap_Input"; if (element >= h->space) { ZOLTAN_PRINT_ERROR(0, yo, "Inserted heap element out of range!\n"); return ZOLTAN_FATAL; } if (h->n >= h->space) { ZOLTAN_PRINT_ERROR(0, yo, "Heap is full!\n"); return ZOLTAN_FATAL; } h->value[element] = value; h->pos[element] = h->n; h->ele[(h->n)++] = element; return ZOLTAN_OK; }
int Zoltan_Drum_Stop_Monitors(ZZ *zz) { int ierr; char *yo = "Zoltan_Drum_Stop_Monitors"; FILE *fp; if ((zz->Drum.use_drum == 0) || (zz->Drum.start_monitors == 0)) return ZOLTAN_OK; if (!zz->Drum.dmm) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "DRUM not initialized"); return ZOLTAN_FATAL; } ierr = DRUM_stopMonitoring(zz->Drum.dmm); if (ierr == DRUM_FATAL) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Unable to stop DRUM monitors"); return ZOLTAN_FATAL; } ierr = DRUM_computePowers(zz->Drum.dmm); if (ierr == DRUM_FATAL) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Unable to compute DRUM powers"); return ZOLTAN_FATAL; } /* print the "power file" if it was requested */ if (zz->Proc == 0 && strcmp(zz->Drum.power_filename,"")) { fp = fopen(zz->Drum.power_filename, "a"); if (fp) { DRUM_printMachineModel(zz->Drum.dmm, fp); fclose(fp); } else { ZOLTAN_PRINT_WARN(zz->Proc, yo, "Could not open power file"); return ZOLTAN_WARN; } } else { if (zz->Proc == 0) { printf("Skipping power file output\n"); fflush(stdout); } } return ZOLTAN_OK; }
int Zoltan_Drum_Start_Monitors(ZZ *zz) { int ierr; char *yo = "Zoltan_Drum_Start_Monitors"; if ((zz->Drum.use_drum == 0) || (zz->Drum.start_monitors == 0)) return ZOLTAN_OK; if (!zz->Drum.dmm) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "DRUM not initialized"); return ZOLTAN_FATAL; } ierr = DRUM_startMonitoring(zz->Drum.dmm); if (ierr == DRUM_FATAL) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Unable to start DRUM monitors"); return ZOLTAN_FATAL; } return ZOLTAN_OK; }
static int DD_Find_Local (Zoltan_DD_Directory *dd, ZOLTAN_ID_PTR gid, /* incoming GID to locate (in) */ ZOLTAN_ID_PTR lid, /* gid's LID (out) */ char *user, /* gid's user data (out) */ int *partition, /* gid's partition number (out) */ int *owner) /* gid's owner (processor number) (out) */ { DD_Node *ptr; DD_NodeIdx nodeidx; int index; char *yo = "DD_Find_Local"; /* input sanity check */ if (dd == NULL || owner == NULL || gid == NULL) { ZOLTAN_PRINT_ERROR ((dd == NULL) ? 0 : dd->my_proc, yo, "Invalid input"); return ZOLTAN_FATAL; } if (dd->debug_level > 5) ZOLTAN_TRACE_IN (dd->my_proc, yo, NULL); /* compute offset into hash table to find head of linked list */ index = Zoltan_DD_Hash2 (gid, dd->gid_length, dd->table_length, dd->hashdata, NULL); /* walk link list until end looking for matching global ID */ for (nodeidx = dd->table[index]; nodeidx != -1; nodeidx = dd->nodelist[nodeidx].next) { ptr = dd->nodelist + nodeidx; if (ZOLTAN_EQ_ID (dd->gid_length, gid, ptr->gid) == TRUE) { /* matching global ID found! Return gid's information */ if (lid) ZOLTAN_SET_ID(dd->lid_length, lid, ptr->gid + dd->gid_length); if (user) memcpy(user, ptr->gid + (dd->gid_length + dd->lid_length), dd->user_data_length); if (owner) *owner = ptr->owner; if (partition) *partition = ptr->partition; if (dd->debug_level > 5) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return ZOLTAN_OK; } } if (owner != NULL) *owner = -1; /* JDT Added -1 owner not found */ if (dd->debug_level > 5) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); if (dd->debug_level > 0) { ZOLTAN_PRINT_INFO(dd->my_proc, yo, "GID not found"); return ZOLTAN_WARN; } return ZOLTAN_WARN; }
void Zoltan_DD_Stats ( Zoltan_DD_Directory *dd) /* directory state information */ { int node_count = 0 ; /* counts Nodes in local directory */ int maxlength = 0; /* length of longest linked list */ int list_count = 0 ; /* number of linked lints in hash table */ int length ; int i ; DD_Node *ptr ; char str[100] ; /* used to build message string */ char *yo = "Zoltan_DD_Stats" ; /* Input sanity check */ if (dd == NULL) { ZOLTAN_PRINT_ERROR (0, yo, "Invalid input argument.") ; return ; } if (dd->debug_level > 4) ZOLTAN_TRACE_IN (dd->my_proc, yo, NULL) ; /* walk down each list in hash table to find every Node */ for (i = 0 ; i < dd->table_length ; i++) { length = 0 ; /* reset length for next count */ if (dd->table[i] != NULL) list_count++ ; /* count of distict linked lists */ for (ptr = dd->table[i] ; ptr != NULL ; ptr = ptr->next) { if (dd->debug_level > 6) { sprintf (str, "GID %4u, Owner %d, Table Index %d.", *ptr->gid, ptr->owner, i) ; ZOLTAN_PRINT_INFO (dd->my_proc, yo, str) ; } length++ ; /* linked list length */ node_count++ ; /* count of Nodes */ } if (length > maxlength) maxlength = length ; /* save length of longest linked list */ } sprintf (str, "Hash table size %d, %d nodes on %d lists, max list length %d.", dd->table_length, node_count, list_count, maxlength) ; ZOLTAN_PRINT_INFO (dd->my_proc, yo, str) ; if (dd->debug_level > 4) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL) ; }