Zoltan is added as thirdParty package

This commit is contained in:
Hamidreza
2025-05-15 21:58:43 +03:30
parent 83a6e4baa1
commit d7479cf1bd
3392 changed files with 318142 additions and 1 deletions

View File

@ -0,0 +1,75 @@
# @HEADER
#
########################################################################
#
# Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
# Copyright 2012 Sandia Corporation
#
# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
# the U.S. Government retains certain rights in this software.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the Corporation nor the names of the
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Questions? Contact Karen Devine kddevin@sandia.gov
# Erik Boman egboman@sandia.gov
#
########################################################################
#
# @HEADER
COMM DIRECTORY -- Package to efficiently perform unstructured communication
operations. The same pattern can be created once and
used repeatedly.
--------------------------------------------------------------------------------
comm_const.h -- Comm_Obj data structure definition and prototypes for
communication package functions.
comm_main.c -- Main routine to test the communication library.
comm_create.c -- Routine to create communication object.
comm_destroy.c -- Free the space allocated for a communication object.
comm_resize.c -- This routine allows the user to describe variable sizes
for the objects to be communicated.
comm_exchange_sizes.c -- When objects are being resized, this updates the
receiving processors' knowledge of message sizes.
comm_do.c -- Routine that uses communication object to actually perform
unstructured communication.
comm_do_reverse.c -- This routine performs the inverse communication of the
operation described in a communication object.
comm_invert_map.c -- Given a set of messages to send, determine the
corresponding set of recieves for each processor
(or vice versa).
comm_sort_ints.c -- Version of quicksort which is used in comm routines.

View File

@ -0,0 +1,161 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef __COMM_H
#define __COMM_H
#include <mpi.h>
#include "zoltan_types.h"
#include "zoltan_util.h"
#include "zoltan_comm.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* Data structures and macros for the Zoltan Communication Package. */
/* This file should be included only by communication package files. */
/* Communication package users should include zoltan_comm.h. */
#ifndef TRUE
#define FALSE (0)
#define TRUE (1)
#endif /* !TRUE */
#define ZOLTAN_COMM_ERROR(a,b,c) \
ZOLTAN_PRINT_ERROR((c),(b),(a));
#define ZOLTAN_COMM_WARNING(a,b,c) \
ZOLTAN_PRINT_WARNING((c),(b),(a));
/* Data structures for communication object. */
struct Zoltan_Comm_Obj { /* data for mapping between decompositions */
int *procs_to; /* processors I'll send to */
int *procs_from; /* processors I'll receive from*/
int *lengths_to; /* # items I send in my messages */
int *lengths_from; /* # items I recv in my messages */
/* Following arrays used if send/recv data is packed contiguously */
int *starts_to; /* where in item lists each send starts */
int *starts_from; /* where in item lists each recv starts */
/* Following arrays used is send/recv data not packed contiguously */
int *indices_to; /* indices of items I send in my msgs */
/* ordered consistent with lengths_to */
int *indices_from; /* indices for where to put arriving data */
/* ordered consistent with lengths_from */
/* Above information is sufficient if items are all of the same size */
/* If item sizes are variable, then need following additional arrays */
int *sizes; /* size of each item to send (if items vary) */
/* Note only on sending processor: */
/* assuming recv proc can figure it out */
int *sizes_to; /* size of each msg to send (if items vary) */
int *sizes_from; /* size of each msg to recv (if items vary) */
/* Following used if send/recv data is packed contiguously & items vary */
int *starts_to_ptr; /* where in dense array sends starts */
int *starts_from_ptr; /* where in dense each recv starts */
/* Following used is send/recv data not packed contiguously & items vary */
int *indices_to_ptr; /* where to find items I send in my msgs */
/* ordered consistent with lengths_to */
int *indices_from_ptr; /* where to find items I recv */
/* ordered consistent with lengths_from */
/* Note: ALL above arrays include data for self-msg */
int nvals; /* number of values I own to start */
int nvals_recv; /* number of values I own after remapping */
int nrecvs; /* number of msgs I'll recv (w/o self_msg) */
int nsends; /* number of msgs I'll send (w/o self_msg) */
int nindices_to;
int nindices_from;
int self_msg; /* do I have data for myself? */
int max_send_size; /* size of longest message I send (w/o self) */
int total_recv_size; /* total amount of data I'll recv (w/ self) */
int maxed_recvs; /* do I have to many receives to post all
* at once? if so use MPI_Alltoallv */
MPI_Comm comm; /* communicator for operation */
MPI_Request *request; /* MPI requests for posted recvs */
MPI_Status *status; /* MPI status for those recvs */
ZOLTAN_COMM_OBJ* plan_reverse; /* to support POST & WAIT */
char* recv_buff; /* To support POST & WAIT */
};
/* Red Storm MPI permits a maximum of 2048 receives. We set our
* limit of posted receives to 2000, leaving some for the application.
*/
#ifndef MPI_RECV_LIMIT
/* Decided for Trilinos v10/Zoltan v3.2 would almost always use */
/* MPI_Alltoall communication instead of point-to-point. */
/* August 2009 */
/* #define MPI_RECV_LIMIT 4 */
/* Decided for zoltan_gid_64 branch to always used posted receives because
* Alltoall requires that offsets be 32-bit integers. October 2010
*/
#define MPI_RECV_LIMIT 0
/* #define MPI_RECV_LIMIT 2000 */
#endif
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif
#endif

View File

@ -0,0 +1,424 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include "comm.h"
#include "zoltan_mem.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* From the mapping of where to send things, construct the communication */
/* data structures. */
/* Note: This routine sets up data structure assuming all objects are the */
/* same size. If this isn't the case, a subsequent call to Comm_Resize */
/* is needed. */
int Zoltan_Comm_Create(
ZOLTAN_COMM_OBJ **cobj, /* returned communicator object */
int nvals, /* number of values I currently own */
int *assign, /* processor assignment for all my values */
MPI_Comm comm, /* communicator for xfer operation */
int tag, /* message tag I can use */
int *pnvals_recv) /* returned # vals I own after communication */
{
ZOLTAN_COMM_OBJ *plan; /* returned communication data structure */
int *starts=NULL; /* pointers into list of vals for procs */
int *lengths_to=NULL; /* lengths of messages I'll send */
int *procs_to=NULL; /* processors I'll send to */
int *indices_to=NULL; /* local_id values I'll be sending */
int *starts_to=NULL; /* where in list my sends begin */
int *lengths_from=NULL; /* lengths of messages I'll receive */
int *procs_from=NULL; /* processors I'll receive from */
int *starts_from=NULL; /* pointers for where to put recv data */
int my_proc; /* my processor tag in communicator */
int nprocs; /* number of processors in communicator */
int max_send_size =0; /* size of longest message I send */
int total_recv_size; /* total size of messages I recv */
int no_send_buff; /* is data nicely grouped by processor? */
int nactive = 0; /* number of values to remap */
int self_msg = 0; /* do I have data for myself? */
int nsends=0; /* # procs I'll send to (including self) */
int nrecvs=0; /* # procs I'll recv from (including self) */
int proc; /* processor I communicate with */
int prev_proc; /* processor on previous loop pass */
int index; /* index into list of objects */
int out_of_mem; /* am I out of memory? */
int comm_flag; /* status flag */
int i, j; /* loop counters */
static char *yo = "Zoltan_Comm_Create";
if (comm == MPI_COMM_NULL){
ZOLTAN_COMM_ERROR("Invalid communicator: MPI_COMM_NULL.", yo, -1);
return ZOLTAN_FATAL;
}
comm_flag = ZOLTAN_OK;
MPI_Comm_rank(comm, &my_proc);
MPI_Comm_size(comm, &nprocs);
/* First check to see if items are grouped by processor with no gaps. */
/* If so, indices_to should be NULL (= identity) */
/* Make data structures that will allow me to traverse arrays quickly. */
/* Begin by determining number of objects I'm sending to each processor. */
starts = (int *) ZOLTAN_MALLOC((nprocs + 1) * sizeof(int));
out_of_mem = FALSE;
if (starts == NULL) {
out_of_mem = TRUE;
goto Mem_Err;
}
/* First, use starts to count values going to each proc. */
for (i = 0; i < nprocs; i++) {
starts[i] = 0;
}
/* Note: Negative assign value means ignore item. */
/* Non-trailing negatives mean data not packed so need send_buf. */
/* Could (but don't) allow negatives between processor blocks w/o buf. */
nactive = 0;
no_send_buff = TRUE;
prev_proc = nprocs;
for (i = 0; i < nvals; i++) {
proc = assign[i];
if (no_send_buff && proc != prev_proc) { /* Checks if blocked by proc */
if (proc >= 0 && (starts[proc] || prev_proc < 0)) {
no_send_buff = FALSE;
}
else {
prev_proc = proc;
}
}
if (proc >= 0) {
++starts[proc];
++nactive;
}
}
self_msg = (starts[my_proc] != 0);
if (no_send_buff) {
/* Grouped by processor. Array indices_to can be NULL (= identity) */
nsends = 0;
for (i = 0; i < nprocs; i++) {
if (starts[i] != 0) ++nsends;
}
indices_to = NULL;
lengths_to = (int *) ZOLTAN_MALLOC(nsends * sizeof(int));
starts_to = (int *) ZOLTAN_MALLOC(nsends * sizeof(int));
procs_to = (int *) ZOLTAN_MALLOC(nsends * sizeof(int));
if (nsends != 0 && (lengths_to == NULL || starts_to == NULL ||
procs_to == NULL)) {
out_of_mem = TRUE;
goto Mem_Err;
}
index = 0;
/* Note that procs_to is in the order the data was passed in. */
for (i = 0; i < nsends; i++) {
starts_to[i] = index;
proc = assign[index];
procs_to[i] = proc;
index += starts[proc];
}
/* Now sort the outgoing procs. */
/* This keeps recvs deterministic if I ever invert communication */
/* It also allows for better balance of traffic in comm_do */
Zoltan_Comm_Sort_Ints(procs_to, starts_to, nsends);
max_send_size = 0;
for (i = 0; i < nsends; i++) {
proc = procs_to[i];
lengths_to[i] = starts[proc];
if (proc != my_proc && lengths_to[i] > max_send_size) {
max_send_size = lengths_to[i];
}
}
}
else { /* Not grouped by processor. More complex data structures. */
/* Sum starts values to be offsets into indices_to array. */
nsends = (starts[0] != 0);
for (i = 1; i < nprocs; i++) {
if (starts[i] != 0)
++nsends;
starts[i] += starts[i - 1];
}
for (i = nprocs - 1; i; i--)
starts[i] = starts[i - 1];
starts[0] = 0;
indices_to = (int *) ZOLTAN_MALLOC(nactive * sizeof(int));
if (nactive != 0 && indices_to == NULL) {
out_of_mem = TRUE;
goto Mem_Err;
}
for (i = 0; i < nvals; i++) {
proc = assign[i];
if (proc >= 0) {
indices_to[starts[proc]] = i;
++starts[proc];
}
}
/* Indices_to array now has the data in clumps for each processor. */
/* Now reconstruct starts array to index into indices_to. */
for (i = nprocs - 1; i; i--) {
starts[i] = starts[i - 1];
}
starts[0] = 0;
starts[nprocs] = nactive;
/* Construct lengths_to, starts_to and procs_to arrays. */
/* Note: If indices_to is needed, procs are in increasing order */
lengths_to = (int *) ZOLTAN_MALLOC(nsends * sizeof(int));
starts_to = (int *) ZOLTAN_MALLOC(nsends * sizeof(int));
procs_to = (int *) ZOLTAN_MALLOC(nsends * sizeof(int));
if (nsends != 0 && (lengths_to == NULL || starts_to == NULL ||
procs_to == NULL)) {
out_of_mem = TRUE;
goto Mem_Err;
}
j = 0;
max_send_size = 0;
for (i = 0; i < nprocs; i++) {
if (starts[i + 1] != starts[i]) {
starts_to[j] = starts[i];
lengths_to[j] = starts[i + 1] - starts[i];
if (i != my_proc && lengths_to[j] > max_send_size) {
max_send_size = lengths_to[j];
}
procs_to[j] = i;
j++;
}
}
}
/* Now change nsends to count only non-self messages */
nsends -= self_msg;
Mem_Err:
ZOLTAN_FREE(&starts);
/* Determine how many messages & what length I'll receive. */
comm_flag = Zoltan_Comm_Invert_Map(lengths_to, procs_to, nsends, self_msg,
&lengths_from, &procs_from, &nrecvs, my_proc, nprocs,
out_of_mem,tag, comm);
starts_from = (int *) ZOLTAN_MALLOC((nrecvs + self_msg) * sizeof(int));
if (starts_from == NULL && nrecvs + self_msg != 0) {
comm_flag = ZOLTAN_MEMERR;
}
else {
j = 0;
for (i = 0; i < nrecvs + self_msg; i++) {
starts_from[i] = j;
j += lengths_from[i];
}
}
if (comm_flag != ZOLTAN_OK) {
if (comm_flag == ZOLTAN_MEMERR) {
ZOLTAN_COMM_ERROR("Out of memory", yo, my_proc);
}
ZOLTAN_FREE(&starts_from);
ZOLTAN_FREE(&indices_to);
ZOLTAN_FREE(&procs_to);
ZOLTAN_FREE(&starts_to);
ZOLTAN_FREE(&lengths_to);
ZOLTAN_FREE(&lengths_from);
ZOLTAN_FREE(&procs_from);
return(comm_flag);
}
total_recv_size = 0;
for (i = 0; i < nrecvs + self_msg; i++)
total_recv_size += lengths_from[i];
plan = (ZOLTAN_COMM_OBJ *) ZOLTAN_MALLOC(sizeof(ZOLTAN_COMM_OBJ));
plan->lengths_to = lengths_to;
plan->starts_to = starts_to;
plan->procs_to = procs_to;
plan->indices_to = indices_to;
plan->lengths_from = lengths_from;
plan->starts_from = starts_from;
plan->procs_from = procs_from;
plan->indices_from = NULL;
plan->sizes = NULL;
plan->sizes_to = NULL;
plan->sizes_from = NULL;
plan->starts_to_ptr = NULL;
plan->starts_from_ptr = NULL;
plan->indices_to_ptr = NULL;
plan->indices_from_ptr = NULL;
plan->nvals = nvals;
plan->nvals_recv = total_recv_size;
plan->nrecvs = nrecvs;
plan->nsends = nsends;
plan->nindices_to = nactive;
plan->nindices_from = 0;
plan->self_msg = self_msg;
plan->max_send_size = max_send_size;
plan->total_recv_size = total_recv_size;
plan->maxed_recvs = 0;
plan->comm = comm;
plan->plan_reverse = NULL;
if (MPI_RECV_LIMIT > 0){
/* If we have a limit to the number of posted receives we are allowed,
** and our plan has exceeded that, then switch to an MPI_Alltoallv so
** that we will have fewer receives posted when we do the communication.
*/
MPI_Allreduce(&nrecvs, &i, 1, MPI_INT, MPI_MAX, comm);
if (i > MPI_RECV_LIMIT){
plan->maxed_recvs = 1;
}
}
if (plan->maxed_recvs){
plan->request = NULL;
plan->status = NULL;
}
else{
plan->request = (MPI_Request *) ZOLTAN_MALLOC(plan->nrecvs * sizeof(MPI_Request));
plan->status = (MPI_Status *) ZOLTAN_MALLOC(plan->nrecvs * sizeof(MPI_Status));
if (plan->nrecvs && ((plan->request == NULL) || (plan->status == NULL)))
comm_flag = ZOLTAN_MEMERR;
}
*pnvals_recv = total_recv_size;
*cobj = plan;
return (comm_flag);
}
#define COPY_BUFFER(buf, type, num) \
if (((num)>0) && from->buf) { \
to->buf = (type *)ZOLTAN_MALLOC((num) * sizeof(type)); \
if (!to->buf) { \
ZOLTAN_PRINT_ERROR(proc, yo, "Insufficient memory."); \
Zoltan_Comm_Destroy(toptr); \
return ZOLTAN_MEMERR; \
} \
memcpy(to->buf, from->buf, (num) * sizeof(type)); \
} \
else { \
to->buf = NULL; \
}
ZOLTAN_COMM_OBJ *Zoltan_Comm_Copy(ZOLTAN_COMM_OBJ *from)
{
ZOLTAN_COMM_OBJ *to = NULL;
Zoltan_Comm_Copy_To(&to, from);
return to;
}
int Zoltan_Comm_Copy_To(ZOLTAN_COMM_OBJ **toptr, ZOLTAN_COMM_OBJ *from)
{
static char *yo = "Zoltan_Comm_Copy_To";
int proc = 0;
ZOLTAN_COMM_OBJ *to= NULL;
if (!toptr){
return ZOLTAN_FATAL;
}
if (*toptr){
Zoltan_Comm_Destroy(toptr);
}
if (from){
MPI_Comm_rank(from->comm, &proc);
to = *toptr = (ZOLTAN_COMM_OBJ *)ZOLTAN_MALLOC(sizeof(ZOLTAN_COMM_OBJ));
*to = *from;
MPI_Comm_dup(from->comm, &(to->comm));
COPY_BUFFER(procs_to, int, to->nsends);
COPY_BUFFER(procs_from, int, to->nrecvs);
COPY_BUFFER(lengths_to, int, to->nsends);
COPY_BUFFER(lengths_from, int, to->nrecvs);
COPY_BUFFER(starts_to, int, to->nsends);
COPY_BUFFER(starts_from, int, to->nrecvs + to->self_msg);
COPY_BUFFER(indices_to, int, to->nindices_to);
COPY_BUFFER(indices_from, int, to->nindices_from);
COPY_BUFFER(sizes, int, to->nvals + 1);
COPY_BUFFER(sizes_to, int, to->nsends + to->self_msg);
COPY_BUFFER(sizes_from, int, to->nrecvs + to->self_msg);
COPY_BUFFER(starts_to_ptr, int, to->nsends + to->self_msg);
COPY_BUFFER(starts_from_ptr, int, to->nrecvs + to->self_msg);
COPY_BUFFER(indices_to_ptr, int, to->nvals);
COPY_BUFFER(indices_from_ptr, int, to->nvals);
COPY_BUFFER(request, MPI_Request, to->nrecvs);
COPY_BUFFER(status, MPI_Status, to->nrecvs);
}
return ZOLTAN_OK;
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,91 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include "comm.h"
#include "zoltan_mem.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
int Zoltan_Comm_Destroy(
ZOLTAN_COMM_OBJ **plan) /* communication data structure pointer */
{
if (*plan == NULL) return ZOLTAN_OK;
/* Free fields of the communication object. */
ZOLTAN_FREE(&((*plan)->status));
ZOLTAN_FREE(&((*plan)->request));
ZOLTAN_FREE(&((*plan)->sizes));
ZOLTAN_FREE(&((*plan)->sizes_to));
ZOLTAN_FREE(&((*plan)->sizes_from));
ZOLTAN_FREE(&((*plan)->starts_to_ptr));
ZOLTAN_FREE(&((*plan)->starts_from_ptr));
ZOLTAN_FREE(&((*plan)->indices_to_ptr));
ZOLTAN_FREE(&((*plan)->indices_from_ptr));
ZOLTAN_FREE(&((*plan)->indices_from));
ZOLTAN_FREE(&((*plan)->indices_to));
ZOLTAN_FREE(&((*plan)->lengths_from));
ZOLTAN_FREE(&((*plan)->starts_to));
ZOLTAN_FREE(&((*plan)->starts_from));
ZOLTAN_FREE(&((*plan)->lengths_to));
ZOLTAN_FREE(&((*plan)->procs_from));
ZOLTAN_FREE(&((*plan)->procs_to));
/* Free the communication object itself */
ZOLTAN_FREE(plan);
return(ZOLTAN_OK);
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,840 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <memory.h>
#include <mpi.h>
#include "comm.h"
#include "zoltan_mem.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#if 0
static void show_int_buffers(int me, int procs, char *buf, int *bcounts, int *boffsets)
{
int i,p;
int *ibuf = (int *)buf;
printf("%d count offset (values)\n",me);
for (p=0; p < procs; p++){
printf("%d %d (",bcounts[p]/4, boffsets[p]/4);
for (i=0; i < bcounts[p]/4; i++){
printf("%d ",*ibuf);
ibuf++;
}
printf(")\n\n");
fflush(stdout);
}
}
#endif
/* Given the communication object, perform a communication operation as
efficiently as possible. */
/* Several cases are supported:
I. All objects are of same size (sizes == NULL)
A. Data is already packed by destination proc (indices_to == NULL)
Can just send straight out of user space.
B. Data not packed by destination proc (indices_to != NULL)
Need to allocate send buff and copy it in before sending
II. Objects of variable sizes (sizes != NULL)
Same two cases above, but offsets are more complicated.
Need stars_to_ptr/_from_ptr to address memory for (A), and
indices_to_ptr/_from_ptr to address memory for (B).
III. On receive, we need to do opposite of the send.
Can receive directly into user space if indices_from == NULL
Otherwise need to receive in buffer and copy.
*/
/*****************************************************************************/
int Zoltan_Comm_Do(
ZOLTAN_COMM_OBJ * plan, /* communication data structure */
int tag, /* message tag for communicating */
char *send_data, /* array of data I currently own */
int nbytes, /* multiplier for sizes */
char *recv_data) /* array of data I'll own after comm */
{
int status = ZOLTAN_OK;
if (!plan->maxed_recvs){
status = Zoltan_Comm_Do_Post (plan, tag, send_data, nbytes, recv_data);
if (status == ZOLTAN_OK)
status = Zoltan_Comm_Do_Wait (plan, tag, send_data, nbytes, recv_data);
}
else{
status = Zoltan_Comm_Do_AlltoAll(plan, send_data, nbytes, recv_data);
}
return status;
}
/*****************************************************************************/
int Zoltan_Comm_Do_Post(
ZOLTAN_COMM_OBJ * plan, /* communication data structure */
int tag, /* message tag for communicating */
char *send_data, /* array of data I currently own */
int nbytes, /* multiplier for sizes */
char *recv_data) /* array of data I'll own after comm */
{
char *send_buff; /* space to buffer outgoing data */
int my_proc; /* processor ID */
size_t self_recv_address = 0;/* where in recv_data self info starts */
int self_num=0; /* where in send list my_proc appears */
size_t offset; /* offset into array I'm copying into */
int self_index = 0; /* send offset for data I'm keeping */
int out_of_mem; /* am I out of memory? */
int nblocks; /* number of procs who need my data */
int proc_index; /* loop counter over procs to send to */
int i, j, k, jj; /* loop counters */
static char *yo = "Zoltan_Comm_Do_Post";
/* Check input parameters */
if (!plan) {
MPI_Comm_rank(MPI_COMM_WORLD, &my_proc);
ZOLTAN_COMM_ERROR("Communication plan = NULL", yo, my_proc);
return ZOLTAN_FATAL;
}
/* If not point to point, currently we do synchroneous communications */
if (plan->maxed_recvs){
int status;
status = Zoltan_Comm_Do_AlltoAll(plan, send_data, nbytes, recv_data);
return (status);
}
MPI_Comm_rank(plan->comm, &my_proc);
if ((plan->nsends + plan->self_msg) && !send_data) {
size_t sum = 0;
if (plan->sizes_to) /* Not an error if all sizes_to == 0 */
for (i = 0; i < (plan->nsends + plan->self_msg); i++)
sum += plan->sizes_to[i];
if (!plan->sizes_to || (plan->sizes_to && sum)) {
ZOLTAN_COMM_ERROR("nsends not zero, but send_data = NULL",
yo, my_proc);
return ZOLTAN_FATAL;
}
}
if ((plan->nrecvs + plan->self_msg) && !recv_data) {
size_t sum = 0;
if (plan->sizes_from) /* Not an error if all sizes_from == 0 */
for (i = 0; i < (plan->nrecvs + plan->self_msg); i++)
sum += plan->sizes_from[i];
if (!plan->sizes_from || (plan->sizes_from && sum)) {
ZOLTAN_COMM_ERROR("nrecvs not zero, but recv_data = NULL",
yo, my_proc);
return ZOLTAN_FATAL;
}
}
if (nbytes < 0) {
ZOLTAN_COMM_ERROR("Scale factor nbytes is negative", yo, my_proc);
return ZOLTAN_FATAL;
}
/* Post irecvs */
out_of_mem = 0;
if (plan->indices_from == NULL) {
/* Data can go directly into user space. */
plan->recv_buff = recv_data;
}
else { /* Need to buffer receive to reorder */
size_t rsize = (size_t) (plan->total_recv_size) * (size_t) nbytes;
plan->recv_buff = (char *) ZOLTAN_MALLOC(rsize);
if (plan->recv_buff == NULL && rsize != 0)
out_of_mem = 1;
}
if (!out_of_mem) {
if (plan->sizes == NULL) { /* All data the same size */
k = 0;
for (i = 0; i < plan->nrecvs + plan->self_msg; i++) {
if (plan->procs_from[i] != my_proc) {
MPI_Irecv((void *)
&plan->recv_buff[(size_t)(plan->starts_from[i]) * (size_t)nbytes],
plan->lengths_from[i] * nbytes,
(MPI_Datatype) MPI_BYTE, plan->procs_from[i], tag,
plan->comm, &plan->request[k]);
k++;
}
else {
self_recv_address = (size_t)(plan->starts_from[i]) * (size_t)nbytes;
}
}
}
else { /* Data of varying sizes */
k = 0;
for (i = 0; i < plan->nrecvs + plan->self_msg; i++) {
if (plan->procs_from[i] != my_proc) {
if (plan->sizes_from[i]) {
MPI_Irecv((void *)
&plan->recv_buff[(size_t)(plan->starts_from_ptr[i])
* (size_t)nbytes],
plan->sizes_from[i] * nbytes,
(MPI_Datatype) MPI_BYTE, plan->procs_from[i],
tag, plan->comm, &plan->request[k]);
}
else
plan->request[k] = MPI_REQUEST_NULL;
k++;
}
else {
self_recv_address = (size_t)(plan->starts_from_ptr[i]) * (size_t)nbytes;
}
}
}
}
/* Do remaining allocation to check for any mem problems. */
if (plan->indices_to != NULL) { /* can't sent straight from input */
size_t ssize = (size_t)(plan->max_send_size) * (size_t)nbytes;
send_buff = (char *) ZOLTAN_MALLOC(ssize);
if (send_buff == 0 && ssize != 0)
out_of_mem = 1;
}
else
send_buff = NULL;
/* Barrier to ensure irecvs are posted before doing any sends. */
/* Simultaneously see if anyone out of memory */
MPI_Allreduce(&out_of_mem, &j, 1, MPI_INT, MPI_SUM, plan->comm);
if (j > 0) { /* Some proc is out of memory -> Punt */
ZOLTAN_FREE(&send_buff);
if (plan->indices_from != NULL)
ZOLTAN_FREE(&plan->recv_buff);
return (ZOLTAN_MEMERR);
}
/* Send out data */
/* Scan through procs_to list to start w/ higher numbered procs */
/* This should balance message traffic. */
nblocks = plan->nsends + plan->self_msg;
proc_index = 0;
while (proc_index < nblocks && plan->procs_to[proc_index] < my_proc)
proc_index++;
if (proc_index == nblocks)
proc_index = 0;
if (plan->sizes == NULL) { /* Data all of same size */
if (plan->indices_to == NULL) { /* data already blocked by processor. */
for (i = proc_index, j = 0; j < nblocks; j++) {
if (plan->procs_to[i] != my_proc) {
MPI_Rsend((void *) &send_data[(size_t)(plan->starts_to[i]) * (size_t)nbytes],
plan->lengths_to[i] * nbytes,
(MPI_Datatype) MPI_BYTE, plan->procs_to[i], tag,
plan->comm);
}
else
self_num = i;
if (++i == nblocks)
i = 0;
}
if (plan->self_msg) { /* Copy data to self. */
/* I use array+offset instead of &(array[offset]) because of
a bug with PGI v9 */
/* I use memmove because I'm not sure that the pointer are not
overlapped. */
memmove(
plan->recv_buff+self_recv_address,
send_data+(size_t)(plan->starts_to[self_num])*(size_t)nbytes,
(size_t) (plan->lengths_to[self_num]) * (size_t) nbytes);
}
}
else { /* Not blocked by processor. Need to buffer. */
for (i = proc_index, jj = 0; jj < nblocks; jj++) {
if (plan->procs_to[i] != my_proc) {
/* Need to pack message first. */
offset = 0;
j = plan->starts_to[i];
for (k = 0; k < plan->lengths_to[i]; k++) {
memcpy(&send_buff[offset],
&send_data[(size_t)(plan->indices_to[j++]) * (size_t)nbytes], nbytes);
offset += nbytes;
}
MPI_Rsend((void *) send_buff, plan->lengths_to[i] * nbytes,
(MPI_Datatype) MPI_BYTE, plan->procs_to[i], tag, plan->comm);
}
else {
self_num = i;
self_index = plan->starts_to[i];
}
if (++i == nblocks)
i = 0;
}
if (plan->self_msg) { /* Copy data to self. */
for (k = 0; k < plan->lengths_to[self_num]; k++) {
memcpy(&plan->recv_buff[self_recv_address],
&send_data[(size_t)(plan->indices_to[self_index++]) * (size_t)nbytes], nbytes);
self_recv_address += nbytes;
}
}
ZOLTAN_FREE(&send_buff);
}
}
else { /* Data of differing sizes */
if (plan->indices_to == NULL) { /* data already blocked by processor. */
for (i = proc_index, j = 0; j < nblocks; j++) {
if (plan->procs_to[i] != my_proc) {
if (plan->sizes_to[i]) {
MPI_Rsend((void *)
&send_data[(size_t)(plan->starts_to_ptr[i]) * (size_t)nbytes],
plan->sizes_to[i] * nbytes,
(MPI_Datatype) MPI_BYTE, plan->procs_to[i],
tag, plan->comm);
}
}
else
self_num = i;
if (++i == nblocks)
i = 0;
}
if (plan->self_msg) { /* Copy data to self. */
if (plan->sizes_to[self_num]) {
char* lrecv = &plan->recv_buff[self_recv_address];
char* lsend = &send_data[(size_t)(plan->starts_to_ptr[self_num]) * (size_t)nbytes];
int sindex = plan->sizes_to[self_num], idx;
for (idx=0; idx<nbytes; idx++) {
memcpy(lrecv, lsend, sindex);
lrecv += sindex;
lsend += sindex;
}
}
}
}
else { /* Not blocked by processor. Need to buffer. */
for (i = proc_index, jj = 0; jj < nblocks; jj++) {
if (plan->procs_to[i] != my_proc) {
/* Need to pack message first. */
offset = 0;
j = plan->starts_to[i];
for (k = 0; k < plan->lengths_to[i]; k++) {
if (plan->sizes[plan->indices_to[j]]) {
memcpy(&send_buff[offset],
&send_data[(size_t)(plan->indices_to_ptr[j]) * (size_t)nbytes],
(size_t)(plan->sizes[plan->indices_to[j]]) * (size_t)nbytes);
offset += (size_t)(plan->sizes[plan->indices_to[j]]) * (size_t)nbytes;
}
j++;
}
if (plan->sizes_to[i]) {
MPI_Rsend((void *) send_buff,
plan->sizes_to[i] * nbytes,
(MPI_Datatype) MPI_BYTE, plan->procs_to[i],
tag, plan->comm);
}
}
else
self_num = i;
if (++i == nblocks)
i = 0;
}
if (plan->self_msg) { /* Copy data to self. */
if (plan->sizes_to[self_num]) {
j = plan->starts_to[self_num];
for (k = 0; k < plan->lengths_to[self_num]; k++) {
int kk = plan->indices_to_ptr[j];
char* lrecv = &plan->recv_buff[self_recv_address];
size_t send_idx = (size_t)kk * (size_t)nbytes;
char* lsend = &send_data[send_idx];
int sindex = plan->sizes[plan->indices_to[j]], idx;
for (idx=0; idx<nbytes; idx++) {
memcpy(lrecv, lsend, sindex);
lrecv += sindex;
lsend += sindex;
}
self_recv_address += (size_t)(plan->sizes[plan->indices_to[j]])
* (size_t) nbytes;
j++;
}
}
}
ZOLTAN_FREE(&send_buff);
}
}
return (ZOLTAN_OK);
}
/*****************************************************************************/
int Zoltan_Comm_Do_Wait(
ZOLTAN_COMM_OBJ * plan, /* communication data structure */
int tag, /* message tag for communicating */
char *send_data, /* array of data I currently own */
int nbytes, /* multiplier for sizes */
char *recv_data) /* array of data I'll own after comm */
{
MPI_Status status; /* return from Waitany */
int my_proc; /* processor ID */
int self_num; /* where in send list my_proc appears */
int i, j, k, jj; /* loop counters */
/* If not point to point, currently we do synchroneous communications */
if (plan->maxed_recvs){
/* Do nothing */
return (ZOLTAN_OK);
}
MPI_Comm_rank(plan->comm, &my_proc);
/* Wait for messages to arrive & unpack them if necessary. */
/* Note: since request is in plan, could wait in later routine. */
if (plan->indices_from == NULL) { /* No copying required */
if (plan->nrecvs > 0) {
MPI_Waitall(plan->nrecvs, plan->request, plan->status);
}
}
else { /* Need to copy into recv_data. */
if (plan->self_msg) { /* Unpack own data before waiting */
for (self_num = 0; self_num < plan->nrecvs + plan->self_msg; self_num++)
if (plan->procs_from[self_num] == my_proc) break;
k = plan->starts_from[self_num];
if (!plan->sizes_from || plan->sizes_from[self_num]) {
for (j = plan->lengths_from[self_num]; j; j--) {
memcpy(&recv_data[(size_t)(plan->indices_from[k]) * (size_t)nbytes],
&plan->recv_buff[(size_t)k * (size_t)nbytes], nbytes);
k++;
}
}
}
else
self_num = plan->nrecvs;
for (jj = 0; jj < plan->nrecvs; jj++) {
MPI_Waitany(plan->nrecvs, plan->request, &i, &status);
if (i == MPI_UNDEFINED) break; /* No more receives */
if (i >= self_num) i++;
k = plan->starts_from[i];
for (j = plan->lengths_from[i]; j; j--) {
memcpy(&recv_data[(size_t)(plan->indices_from[k]) * (size_t)nbytes],
&plan->recv_buff[(size_t)k * (size_t)nbytes], nbytes);
k++;
}
}
ZOLTAN_FREE(&plan->recv_buff);
}
return (ZOLTAN_OK);
}
/*****************************************************************************/
/* Do_Post would require posting more receives than allowed on this platform.
* We use MPI_AlltoAllv instead, which is probably implemented such that each
* process does one receive at a time.
*/
int Zoltan_Comm_Do_AlltoAll(
ZOLTAN_COMM_OBJ * plan, /* communication data structure */
char *send_data, /* array of data I currently own */
int nbytes, /* multiplier for sizes */
char *recv_data) /* array of data I'll own after comm */
{
static char *yo = "Zoltan_Comm_Do_AlltoAll";
char *outbuf=NULL, *inbuf=NULL, *buf=NULL;
int *outbufCounts=NULL, *outbufOffsets=NULL;
int *inbufCounts=NULL, *inbufOffsets=NULL;
int nprocs, me, i, j, k, p, sorted;
int nSendMsgs, nSendItems, nRecvMsgs, nRecvItems;
int length, offset, itemSize, outbufLen;
int sm = (plan->self_msg > 0) ? 1 : 0;
nSendMsgs = plan->nsends + sm;
nRecvMsgs = plan->nrecvs + sm;
for (i=0, nSendItems=0; i <nSendMsgs; i++){
nSendItems += plan->lengths_to[i];
}
for (i=0, nRecvItems=0; i <nRecvMsgs; i++){
nRecvItems += plan->lengths_from[i];
}
MPI_Comm_size(plan->comm, &nprocs);
MPI_Comm_rank(plan->comm, &me);
outbufCounts = (int *) ZOLTAN_CALLOC(nprocs , sizeof(int));
outbufOffsets = (int *) ZOLTAN_CALLOC(nprocs , sizeof(int));
inbufCounts = (int *) ZOLTAN_CALLOC(nprocs , sizeof(int));
inbufOffsets = (int *) ZOLTAN_CALLOC(nprocs , sizeof(int));
if (!outbufCounts || !outbufOffsets || !inbufCounts || !inbufOffsets){
ZOLTAN_COMM_ERROR("memory error", yo, me);
}
/* The *_to fields of the plan refer to the items in the send_data buffer,
* and how to pull out the correct items for each receiver. The
* *_from fields of the plan refer to the recv_data buffer. Items
* arrive in process rank order, and these fields tell us where to
* put them in the recv_data buffer.
*/
/* CREATE SEND BUFFER */
sorted = 0;
if (plan->indices_to == NULL){
sorted = 1;
for (i=1; i< nSendMsgs; i++){
if (plan->starts_to[i] < plan->starts_to[i-1]){
sorted = 0;
break;
}
}
}
if (plan->sizes_to){
/*
* Each message contains items for a process, and each item may be
* a different size.
*/
for (i=0, outbufLen=0; i < nSendMsgs; i++){
outbufLen += plan->sizes_to[i];
}
if (plan->indices_to){
/*
* items are not grouped by message
*/
buf = outbuf = (char *)ZOLTAN_MALLOC((size_t)outbufLen * (size_t)nbytes);
if (outbufLen && nbytes && !outbuf){
ZOLTAN_COMM_ERROR("memory error", yo, me);
}
for (p=0, i=0, k=0; p < nprocs; p++){
length = 0;
if (i < nSendMsgs){
if (plan->procs_to[i] == p){ /* procs_to is sorted */
for (j=0; j < plan->lengths_to[i]; j++,k++){
itemSize = plan->sizes[plan->indices_to[k]] * nbytes;
offset = plan->indices_to_ptr[k] * nbytes;
memcpy(buf, send_data + offset, itemSize);
buf += itemSize;
length += itemSize;
}
i++;
}
}
outbufCounts[p] = length;
if (p){
outbufOffsets[p] = outbufOffsets[p-1] + outbufCounts[p-1];
}
}
}
else{
/*
* items are stored contiguously for each message
*/
if (!sorted || (plan->nvals > nSendItems) ){
buf = outbuf = (char *)ZOLTAN_MALLOC((size_t)outbufLen * (size_t)nbytes);
if (outbufLen && nbytes && !outbuf){
ZOLTAN_COMM_ERROR("memory error", yo, me);
}
}
else{
/* All items in send_data are being sent, and they are sorted
* in process rank order.
*/
outbuf = send_data;
}
for (p=0, i=0; p < nprocs; p++){
length = 0;
if (i < nSendMsgs){
if (plan->procs_to[i] == p){ /* procs_to is sorted */
length = plan->sizes_to[i] * nbytes;
offset = plan->starts_to_ptr[i] * nbytes;
if ((!sorted || (plan->nvals > nSendItems)) && length){
memcpy(buf, send_data + offset, length);
buf += length;
}
i++;
}
}
outbufCounts[p] = length;
if (p){
outbufOffsets[p] = outbufOffsets[p-1] + outbufCounts[p-1];
}
}
}
}
else if (plan->indices_to){
/*
* item sizes are constant, however the items belonging in a given
* message may not be contiguous in send_data
*/
buf = outbuf = (char *)ZOLTAN_MALLOC((size_t)nSendItems * (size_t)nbytes);
if (nSendMsgs && nbytes && !outbuf){
ZOLTAN_COMM_ERROR("memory error", yo, me);
}
for (p=0, i=0, k=0; p < nprocs; p++){
length = 0;
if (i < nSendMsgs){
if (plan->procs_to[i] == p){ /* procs_to is sorted */
for (j=0; j < plan->lengths_to[i]; j++,k++){
offset = plan->indices_to[k] * nbytes;
memcpy(buf, send_data + offset, nbytes);
buf += nbytes;
}
length = plan->lengths_to[i] * nbytes;
i++;
}
}
outbufCounts[p] = length;
if (p){
outbufOffsets[p] = outbufOffsets[p-1] + outbufCounts[p-1];
}
}
}
else{
/* item sizes are constant, and items belonging to a
* given message are always stored contiguously in send_data
*/
if (!sorted || (plan->nvals > nSendItems)){
buf = outbuf = (char *)ZOLTAN_MALLOC((size_t)nSendItems * (size_t)nbytes);
if (nSendItems && nbytes && !outbuf){
ZOLTAN_COMM_ERROR("memory error", yo, me);
}
}
else{
/* send_data is sorted by process, and we don't skip
* any of the data in the buffer, so we can use send_data
* in the alltoall call
*/
outbuf = send_data;
}
for (p=0,i=0; p < nprocs; p++){
length = 0;
if (i < nSendMsgs){
if (plan->procs_to[i] == p){ /* procs_to is sorted */
offset = plan->starts_to[i] * nbytes;
length = plan->lengths_to[i] * nbytes;
if ((!sorted || (plan->nvals > nSendItems)) && length){
memcpy(buf, send_data + offset, length);
buf += length;
}
i++;
}
}
outbufCounts[p] = length;
if (p){
outbufOffsets[p] = outbufOffsets[p-1] + outbufCounts[p-1];
}
}
}
/* CREATE RECEIVE BUFFER */
sorted = 0;
if (plan->indices_from == NULL){
sorted = 1;
for (i=1; i< nRecvMsgs; i++){
if (plan->starts_from[i] < plan->starts_from[i-1]){
sorted = 0;
break;
}
}
}
if (sorted){
/* Caller already expects received data to be ordered by
* the sending process rank.
*/
inbuf = recv_data;
}
else{
inbuf = (char *)ZOLTAN_MALLOC((size_t)(plan->total_recv_size) * (size_t)nbytes);
if (plan->total_recv_size && nbytes && !inbuf){
ZOLTAN_COMM_ERROR("memory error", yo, me);
}
}
for (p=0, i=0; p < nprocs; p++){
length = 0;
if (i < nRecvMsgs){
if (plan->procs_from[i] == p){
if (plan->sizes == NULL){
length = plan->lengths_from[i] * nbytes;
}
else{
length = plan->sizes_from[i] * nbytes;
}
i++;
}
}
inbufCounts[p] = length;
if (p){
inbufOffsets[p] = inbufOffsets[p-1] + inbufCounts[p-1];
}
}
/* EXCHANGE DATA */
MPI_Alltoallv(outbuf, outbufCounts, outbufOffsets, MPI_BYTE,
inbuf, inbufCounts, inbufOffsets, MPI_BYTE,
plan->comm);
if (outbuf != send_data){
ZOLTAN_FREE(&outbuf);
}
ZOLTAN_FREE(&outbufCounts);
ZOLTAN_FREE(&outbufOffsets);
/* WRITE RECEIVED DATA INTO USER'S BUFFER WHERE IT'S EXPECTED */
if (!sorted){
buf = inbuf;
if (plan->sizes == NULL){
/* each item in each message is nbytes long */
if (plan->indices_from == NULL){
for (i=0; i < nRecvMsgs; i++){
offset = plan->starts_from[i] * nbytes;
length = plan->lengths_from[i] * nbytes;
memcpy(recv_data + offset, buf, length);
buf += length;
}
}
else{
for (i=0,k=0; i < nRecvMsgs; i++){
for (j=0; j < plan->lengths_from[i]; j++,k++){
offset = plan->indices_from[k] * nbytes;
memcpy(recv_data + offset, buf, nbytes);
buf += nbytes;
}
}
}
}
else{ /* (sizes!=NULL) && (indices_from!=NULL) not allowed by Zoltan_Comm_Resize */
/* items can be different sizes */
for (i=0; i < nRecvMsgs; i++){
offset = plan->starts_from_ptr[i] * nbytes;
length = plan->sizes_from[i] * nbytes;
memcpy(recv_data + offset, buf, length);
buf += length;
}
}
ZOLTAN_FREE(&inbuf);
}
ZOLTAN_FREE(&inbufCounts);
ZOLTAN_FREE(&inbufOffsets);
return ZOLTAN_OK;
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,278 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include "zoltan_mem.h"
#include "comm.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
static void free_reverse_plan(ZOLTAN_COMM_OBJ *plan)
{
if (plan && (plan->plan_reverse != NULL)) {
if (plan->plan_reverse->sizes != NULL) {
ZOLTAN_FREE(&plan->plan_reverse->sizes);
ZOLTAN_FREE(&plan->plan_reverse->sizes_to);
ZOLTAN_FREE(&plan->plan_reverse->sizes_from);
ZOLTAN_FREE(&plan->plan_reverse->starts_to_ptr);
ZOLTAN_FREE(&plan->plan_reverse->starts_from_ptr);
ZOLTAN_FREE(&plan->plan_reverse->indices_to_ptr);
ZOLTAN_FREE(&plan->plan_reverse->indices_from_ptr);
}
ZOLTAN_FREE(&(plan->plan_reverse->status));
ZOLTAN_FREE(&(plan->plan_reverse->request));
ZOLTAN_FREE(&plan->plan_reverse);
}
}
static int create_reverse_plan(
ZOLTAN_COMM_OBJ *plan, /* communication data structure */
int tag,
int *sizes) /* variable size of objects (if not NULL) */
{
int total_send_length;/* total message length I send in plan */
int max_recv_length; /* biggest message I recv in plan */
int sum_recv_sizes; /* sum of the item sizes I receive */
int comm_flag; /* status flag */
int i; /* loop counter */
static char *yo = "Zoltan_Comm_Reverse_Plan";
/* Check input parameters */
if (!plan){
ZOLTAN_COMM_ERROR("Communication plan = NULL.", yo, -1);
return ZOLTAN_FATAL;
}
/* Let Zoltan_Comm_Do check the remaining parameters. */
total_send_length = 0;
for (i = 0; i < plan->nsends + plan->self_msg; i++) {
total_send_length += plan->lengths_to[i];
}
max_recv_length = 0;
for (i = 0; i < plan->nrecvs; i++) {
if (plan->lengths_from[i] > max_recv_length)
max_recv_length = plan->lengths_from[i];
}
plan->plan_reverse =(ZOLTAN_COMM_OBJ*)ZOLTAN_MALLOC(sizeof(ZOLTAN_COMM_OBJ));
plan->plan_reverse->nvals = plan->nvals_recv;
plan->plan_reverse->nvals_recv = plan->nvals;
plan->plan_reverse->lengths_to = plan->lengths_from;
plan->plan_reverse->procs_to = plan->procs_from;
plan->plan_reverse->indices_to = plan->indices_from;
plan->plan_reverse->starts_to = plan->starts_from;
plan->plan_reverse->lengths_from = plan->lengths_to;
plan->plan_reverse->procs_from = plan->procs_to;
plan->plan_reverse->indices_from = plan->indices_to;
plan->plan_reverse->starts_from = plan->starts_to;
plan->plan_reverse->nrecvs = plan->nsends;
plan->plan_reverse->nsends = plan->nrecvs;
plan->plan_reverse->self_msg = plan->self_msg;
plan->plan_reverse->max_send_size = max_recv_length;
plan->plan_reverse->total_recv_size = total_send_length;
plan->plan_reverse->comm = plan->comm;
plan->plan_reverse->sizes = NULL;
plan->plan_reverse->sizes_to = NULL;
plan->plan_reverse->sizes_from = NULL;
plan->plan_reverse->starts_to_ptr = NULL;
plan->plan_reverse->starts_from_ptr = NULL;
plan->plan_reverse->indices_to_ptr = NULL;
plan->plan_reverse->indices_from_ptr = NULL;
plan->plan_reverse->maxed_recvs = 0;
plan->plan_reverse->plan_reverse = NULL;
plan->plan_reverse->recv_buff = NULL;
if (MPI_RECV_LIMIT > 0){
/* If we have a limit to the number of posted receives we are allowed,
** and our plan has exceeded that, then switch to an MPI_Alltoallv so
** that we will have fewer receives posted when we do the communication.
*/
MPI_Allreduce(&plan->nsends, &i, 1, MPI_INT, MPI_MAX, plan->comm);
if (i > MPI_RECV_LIMIT){
plan->plan_reverse->maxed_recvs = 1;
}
}
if (plan->plan_reverse->maxed_recvs){
plan->plan_reverse->request = NULL;
plan->plan_reverse->status = NULL;
}
else{
plan->plan_reverse->request = (MPI_Request *)
ZOLTAN_MALLOC(plan->plan_reverse->nrecvs * sizeof(MPI_Request));
if (plan->plan_reverse->request == NULL && plan->plan_reverse->nrecvs != 0) {
return(ZOLTAN_MEMERR);
}
plan->plan_reverse->status = (MPI_Status *)
ZOLTAN_MALLOC(plan->plan_reverse->nrecvs * sizeof(MPI_Status));
if (plan->plan_reverse->status == NULL && plan->plan_reverse->nrecvs != 0) {
return(ZOLTAN_MEMERR);
}
}
comm_flag =Zoltan_Comm_Resize(plan->plan_reverse,sizes,tag,&sum_recv_sizes);
if (comm_flag != ZOLTAN_OK) {
return(comm_flag);
}
if (sum_recv_sizes != plan->plan_reverse->total_recv_size){
/* Sanity check */
return(ZOLTAN_FATAL);
}
return ZOLTAN_OK;
}
/******************************************************************************/
int Zoltan_Comm_Do_Reverse(
ZOLTAN_COMM_OBJ *plan, /* communication data structure */
int tag, /* message tag for communicating */
char *send_data, /* array of data I currently own */
int nbytes, /* # bytes per data item */
int *sizes, /* variable size of objects (if not NULL) */
char *recv_data) /* array of data I'll own after reverse comm */
{
int status;
/* create plan->plan_reverse
*/
status = create_reverse_plan(plan, tag, sizes);
if (status == ZOLTAN_OK){
if (plan->plan_reverse->maxed_recvs){
/* use MPI_Alltoallv to implement plan->plan_reverse, because comm_do_post
* would post more receives that allowed on this machine
*/
status = Zoltan_Comm_Do_AlltoAll(plan->plan_reverse, send_data, nbytes, recv_data);
}
else{
/* use post/wait which is faster when each sends to few
*/
status = Zoltan_Comm_Do_Post(plan->plan_reverse, tag, send_data, nbytes, recv_data);
if (status == ZOLTAN_OK){
status = Zoltan_Comm_Do_Wait (plan->plan_reverse, tag, send_data, nbytes, recv_data);
}
}
}
free_reverse_plan(plan);
return status;
}
/******************************************************************************/
/* Perform a reverse communication operation. Communication object describes */
/* an action, and this routine does the opposite. Can be used to return */
/* updated data to originating processor. */
int Zoltan_Comm_Do_Reverse_Post(
ZOLTAN_COMM_OBJ *plan, /* communication data structure */
int tag, /* message tag for communicating */
char *send_data, /* array of data I currently own */
int nbytes, /* # bytes per data item */
int *sizes, /* variable size of objects (if not NULL) */
char *recv_data) /* array of data I'll own after reverse comm */
{
int comm_flag; /* status flag */
/* create plan->plan_reverse
*/
comm_flag = create_reverse_plan(plan, tag, sizes);
if (comm_flag == ZOLTAN_OK){
/* post the receives of plan->plan_reverse
*/
comm_flag = Zoltan_Comm_Do_Post(plan->plan_reverse, tag, send_data, nbytes,
recv_data);
}
if (comm_flag != ZOLTAN_OK){
free_reverse_plan(plan);
}
return (comm_flag);
}
/******************************************************************************/
int Zoltan_Comm_Do_Reverse_Wait(
ZOLTAN_COMM_OBJ *plan, /* communication data structure */
int tag, /* message tag for communicating */
char *send_data, /* array of data I currently own */
int nbytes, /* # bytes per data item */
int *sizes, /* variable size of objects (if not NULL) */
char *recv_data) /* array of data I'll own after reverse comm */
{
int comm_flag; /* status flag */
comm_flag = Zoltan_Comm_Do_Wait(plan->plan_reverse, tag, send_data, nbytes, recv_data);
free_reverse_plan(plan);
return(comm_flag);
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,104 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <mpi.h>
#include "comm.h"
#include "zoltan_mem.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
int Zoltan_Comm_Exchange_Sizes(
int *sizes_to, /* value I need to exchange (size of true msg) */
int *procs_to, /* procs I send to */
int nsends, /* number of messages I'll send */
int self_msg, /* do I copy data to myself? */
int *sizes_from, /* (returned) size of all my receives */
int *procs_from, /* procs I recv from */
int nrecvs, /* number of messages I receive */
int *total_recv_size, /* (returned) sum of all incoming sizes */
int my_proc, /* my processor number */
int tag, /* message tag I can use */
MPI_Comm comm) { /* communicator */
int self_index_to; /* location of self in procs_to */
MPI_Status status; /* status of commuication operation */
int i; /* loop counter */
/* If sizes vary, then I need to communicate message lengths */
self_index_to = -1;
for (i = 0; i < nsends + self_msg; i++) {
if (procs_to[i] != my_proc)
MPI_Send((void *) &sizes_to[i], 1, MPI_INT, procs_to[i], tag, comm);
else
self_index_to = i;
}
*total_recv_size = 0;
for (i = 0; i < nrecvs + self_msg; i++) {
if (procs_from[i] != my_proc)
MPI_Recv((void *) &sizes_from[i], 1, MPI_INT, procs_from[i],
tag, comm, &status);
else
sizes_from[i] = sizes_to[self_index_to];
*total_recv_size += sizes_from[i];
}
return (ZOLTAN_OK);
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,176 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <memory.h>
#include <mpi.h>
#include "comm.h"
#include "zoltan_mem.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* Given the communication plan, return information about the plan. */
/* All array memory must be allocated by the calling routines, and */
/* is assumed to be of the correct size. */
/* Values are not returned when arguments are NULL. */
int Zoltan_Comm_Info(
ZOLTAN_COMM_OBJ *plan, /* communication data structure */
int *nsends, /* number of sends in plan */
int *send_procs, /* list of procs to which messages are sent */
int *send_lengths, /* number of values to be sent to each proc
in procs_to */
int *send_nvals, /* number of values to send */
int *send_max_size, /* max size of msg to be sent. */
int *send_list, /* proc assignment of each value to be sent
(same as "assign" in Zoltan_Comm_Create) */
int *nrecvs, /* number of receives in plan */
int *recv_procs, /* list of procs from which messages are
received. */
int *recv_lengths, /* number of values to be received from each
proc in procs_from */
int *recv_nvals, /* number of values to recv */
int *recv_total_size, /* total size of items to be received. */
int *recv_list, /* proc assignment of each value to be received
(inverse of sent_list) */
int *self_msg /* number of self-messages in plan */
)
{
static char *yo = "Zoltan_Comm_Info";
int i, j, k, my_proc;
/* Check input parameters */
if (!plan) {
MPI_Comm_rank(MPI_COMM_WORLD, &my_proc);
ZOLTAN_COMM_ERROR("Communication plan = NULL", yo, my_proc);
return ZOLTAN_FATAL;
}
if (nsends)
*nsends = plan->nsends;
if (send_procs)
for (i = 0; i < plan->nsends + plan->self_msg; i++)
send_procs[i] = plan->procs_to[i];
if (send_lengths)
for (i = 0; i < plan->nsends + plan->self_msg; i++)
send_lengths[i] = plan->lengths_to[i];
if (send_nvals)
*send_nvals = plan->nvals;
if (send_max_size)
*send_max_size = plan->max_send_size;
if (send_list) {
for (i = 0; i < plan->nvals; i++) send_list[i] = -1;
if (plan->indices_to == NULL) {
for (i = 0; i < plan->nsends + plan->self_msg; i++) {
k = plan->starts_to[i];
for (j = 0; j < plan->lengths_to[i]; j++)
send_list[k+j] = plan->procs_to[i];
}
}
else {
for (i = 0; i < plan->nsends + plan->self_msg; i++) {
k = plan->starts_to[i];
for (j = 0; j < plan->lengths_to[i]; j++)
send_list[plan->indices_to[k+j]] = plan->procs_to[i];
}
}
}
if (nrecvs)
*nrecvs = plan->nrecvs;
if (recv_procs)
for (i = 0; i < plan->nrecvs + plan->self_msg; i++)
recv_procs[i] = plan->procs_from[i];
if (recv_lengths)
for (i = 0; i < plan->nrecvs + plan->self_msg; i++)
recv_lengths[i] = plan->lengths_from[i];
if (recv_nvals)
*recv_nvals = plan->nvals_recv;
if (recv_total_size)
*recv_total_size = plan->total_recv_size;
if (recv_list) {
for (i = 0; i < plan->nvals_recv; i++) recv_list[i] = -1;
if (plan->indices_from == NULL) {
for (i = 0; i < plan->nrecvs + plan->self_msg; i++) {
k = plan->starts_from[i];
for (j = 0; j < plan->lengths_from[i]; j++)
recv_list[k+j] = plan->procs_from[i];
}
}
else {
for (i = 0; i < plan->nrecvs + plan->self_msg; i++) {
k = plan->starts_from[i];
for (j = 0; j < plan->lengths_from[i]; j++)
recv_list[plan->indices_from[k+j]] = plan->procs_from[i];
}
}
}
if (self_msg)
*self_msg = plan->self_msg;
return (ZOLTAN_OK);
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,225 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <mpi.h>
#include "comm.h"
#include "zoltan_mem.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* Knowing who I send to, determine how many messages I'll receive, */
/* and their lengths. Upon entry, the arrays "lengths_to" and "procs_to" */
/* contain list of processors I send to and the lengths of the corresponding */
/* messages. Upon exit, "lengths_from" and "procs_from" contain receive info. */
/* Note: By reinterpreting "to" and "from", this routine can do the opposite: */
/* given "from" data it computes "to" data. */
/* Data is allowed to be mapped from me to me. */
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
int Zoltan_Comm_Invert_Map(
int *lengths_to, /* number of items I'm sending */
int *procs_to, /* procs I send to */
int nsends, /* number of messages I'll send */
int self_msg, /* do I copy data to myself? */
int **plengths_from, /* number of items I'm receiving */
int **pprocs_from, /* procs I recv lengths from */
int *pnrecvs, /* number of messages I receive */
int my_proc, /* my processor number */
int nprocs, /* total number of processors */
int out_of_mem, /* tell everyone I'm out of memory? */
int tag, /* message tag I can use */
MPI_Comm comm) /* communicator */
{
int *lengths_from; /* lengths of my recvs */
int *procs_from; /* procs I recv lengths from */
int *msg_count; /* binary flag for procs I send to (nprocs) */
int *counts; /* argument to Reduce_scatter */
int nrecvs=0; /* number of messages I'll receive */
int i,j; /* loop counter */
MPI_Status status; /* return MPI argument */
MPI_Request *req = NULL;
int local_out_of_mem; /* Temporary variable to work-around a compiler
bug; see comments below. */
int max_nrecvs;
int *sendbuf=NULL, *recvbuf=NULL;
msg_count = (int *) ZOLTAN_MALLOC(nprocs * sizeof(int));
counts = (int *) ZOLTAN_MALLOC(nprocs * sizeof(int));
if (msg_count == NULL || counts == NULL) out_of_mem = 1;
/* Work-around for compiler bug suggested by Rich Schiek.
* With 64-bit linux, OpenMPI 1.2.5, and Intel 10.1 compilers with
* optimization, passing the address of out_of_mem to MPI_Allreduce
* causes a crash in MPI_Allreduce. Rich and Tom Russo theorize that in
* Zoltan_Comm_Create, out_of_mem is stored in a register, and taking
* the address of a register is undefined. Copying out_of_mem to a
* local variable avoids the problem.
* See Zoltan Bugzilla bug 3825 for more info.
*/
local_out_of_mem = out_of_mem;
MPI_Allreduce((void *) &local_out_of_mem, (void *) &i, 1, MPI_INT, MPI_MAX, comm);
if (i) {
ZOLTAN_FREE(&counts);
ZOLTAN_FREE(&msg_count);
return(ZOLTAN_MEMERR);
}
for (i = 0; i < nprocs; i++) {
msg_count[i] = 0;
counts[i] = 1;
}
for (i = 0; i < nsends + self_msg; i++)
msg_count[procs_to[i]] = 1;
/*
* KDDKDD: Replaced MPI_Reduce_scatter with MPI_Reduce and MPI_Scatter
* KDDKDD: to avoid reported problems with MPICH 1.5.2.1.
* KDDKDD: Some sort of MPI_TYPE_INDEXED error.
* KDDKDD: Bug fix suggested by Clark Dohrmann and Rob Hoekstra.
* KDDKDD: July 20, 2004
MPI_Reduce_scatter((void *) msg_count, (void *) &nrecvs, counts, MPI_INT,
MPI_SUM, comm);
*/
MPI_Reduce(msg_count, counts, nprocs, MPI_INT, MPI_SUM, 0, comm);
MPI_Scatter(counts, 1, MPI_INT, &nrecvs, 1, MPI_INT, 0, comm);
max_nrecvs = 0;
if (my_proc == 0){
for (i=0; i < nprocs; i++){
if (counts[i] > max_nrecvs)
max_nrecvs = counts[i];
}
}
MPI_Bcast(&max_nrecvs, 1, MPI_INT, 0, comm);
ZOLTAN_FREE(&counts);
ZOLTAN_FREE(&msg_count);
lengths_from = (int *) ZOLTAN_MALLOC(nrecvs*sizeof(int));
procs_from = (int *) ZOLTAN_MALLOC(nrecvs*sizeof(int));
/* Note: these mallocs should never fail as prior frees are larger. */
if (MPI_RECV_LIMIT == 0 || max_nrecvs <= MPI_RECV_LIMIT){
req = (MPI_Request *)ZOLTAN_MALLOC(sizeof(MPI_Request) * nrecvs);
if (!req && nrecvs){
ZOLTAN_FREE(&lengths_from);
ZOLTAN_FREE(&procs_from);
return(ZOLTAN_MEMERR);
}
/* Note: I'm counting on having a unique tag or some of my incoming */
/* messages might get confused with others. */
for (i=0; i < nrecvs; i++){
MPI_Irecv(lengths_from + i, 1, MPI_INT, MPI_ANY_SOURCE, tag, comm, req + i);
}
for (i=0; i < nsends+self_msg; i++){
MPI_Send(lengths_to + i, 1, MPI_INT, procs_to[i], tag, comm);
}
for (i=0; i < nrecvs; i++){
MPI_Wait(req + i, &status);
procs_from[i] = status.MPI_SOURCE;
}
ZOLTAN_FREE(&req);
}
else{ /* some large HPC machines have a limit on number of posted receives */
sendbuf = (int *)ZOLTAN_CALLOC(sizeof(int) , nprocs);
recvbuf = (int *)ZOLTAN_MALLOC(sizeof(int) * nprocs);
if (!sendbuf || !recvbuf){
ZOLTAN_FREE(&lengths_from);
ZOLTAN_FREE(&procs_from);
return(ZOLTAN_MEMERR);
}
for (i=0; i < nsends + self_msg; i++){
sendbuf[procs_to[i]] = lengths_to[i];
}
MPI_Alltoall(sendbuf, 1, MPI_INT, recvbuf, 1, MPI_INT, comm);
ZOLTAN_FREE(&sendbuf);
for (i=0, j=0; i < nprocs; i++){
if (recvbuf[i] > 0){
lengths_from[j] = recvbuf[i];
procs_from[j] = i;
if (++j == nrecvs) break;
}
}
ZOLTAN_FREE(&recvbuf);
}
/* Sort recv lists to keep execution deterministic (e.g. for debugging) */
Zoltan_Comm_Sort_Ints(procs_from, lengths_from, nrecvs);
*plengths_from = lengths_from;
*pprocs_from = procs_from;
*pnrecvs = nrecvs - self_msg; /* Only return number of true messages */
return(ZOLTAN_OK);
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,182 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include "comm.h"
#include "zoltan_mem.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/*
* Given a communication plan, invert the plan for the reverse communication.
* The sizes in the inverted plan are assumed to be uniform.
* The input plan is overwritten with the inverted plan.
* If an error occurs, the old plan is returned unchanged.
* Note: receives in new plan are blocked, even if sends in old
* plan were not. This blocking allows variable sized sends to be
* done with the new plan (Zoltan_Comm_Resize). However, it also means
* the new plan can not do exactly what Zoltan_Comm_Do_Reverse can do.
* If the application cares about the order of received data, it should
* not use this routine.
*/
int Zoltan_Comm_Invert_Plan(
ZOLTAN_COMM_OBJ **plan /* communicator object to be inverted */
)
{
static char *yo = "Zoltan_Comm_Invert_Plan";
ZOLTAN_COMM_OBJ *old = *plan, *new = NULL;
int i, ierr = ZOLTAN_OK;
int total_send_length;
int max_recv_length;
if (old == NULL){
ZOLTAN_COMM_ERROR("NULL input plan.", yo, -1);
ierr = ZOLTAN_FATAL;
goto End;
}
total_send_length = 0;
for (i = 0; i < old->nsends + old->self_msg; i++) {
total_send_length += old->lengths_to[i];
}
max_recv_length = 0;
for (i = 0; i < old->nrecvs; i++) {
if (old->lengths_from[i] > max_recv_length)
max_recv_length = old->lengths_from[i];
}
new = (ZOLTAN_COMM_OBJ *) ZOLTAN_MALLOC(sizeof(ZOLTAN_COMM_OBJ));
if (!new) {
ierr = ZOLTAN_MEMERR;
goto End;
}
new->lengths_to = old->lengths_from;
new->starts_to = old->starts_from;
new->procs_to = old->procs_from;
new->indices_to = old->indices_from;
new->lengths_from = old->lengths_to;
new->starts_from = old->starts_to;
new->procs_from = old->procs_to;
new->indices_from = NULL; /* In new plan, receives are blocked. */
/* Assumption: uniform object sizes in output plans. */
/* Can be changed by later calls to Zoltan_Comm_Resize. */
new->sizes = NULL;
new->sizes_to = NULL;
new->sizes_from = NULL;
new->starts_to_ptr = NULL;
new->starts_from_ptr = NULL;
new->indices_to_ptr = NULL;
new->indices_from_ptr = NULL;
new->nvals = old->nvals_recv;
new->nvals_recv = old->nvals;
new->nrecvs = old->nsends;
new->nsends = old->nrecvs;
new->self_msg = old->self_msg;
new->max_send_size = max_recv_length;
new->total_recv_size = total_send_length;
new->comm = old->comm;
new->maxed_recvs = 0;
if (MPI_RECV_LIMIT > 0){
/* If we have a limit to the number of posted receives we are allowed,
** and our plan has exceeded that, then switch to an MPI_Alltoallv so
** that we will have fewer receives posted when we do the communication.
*/
MPI_Allreduce(&new->nrecvs, &i, 1, MPI_INT, MPI_MAX, new->comm);
if (i > MPI_RECV_LIMIT){
new->maxed_recvs = 1;
}
}
if (new->maxed_recvs){
new->request = NULL;
new->status = NULL;
}
else{
new->request = (MPI_Request *) ZOLTAN_MALLOC(new->nrecvs*sizeof(MPI_Request));
new->status = (MPI_Status *) ZOLTAN_MALLOC(new->nrecvs*sizeof(MPI_Status));
if (new->nrecvs && ((new->request == NULL) || (new->status == NULL))) {
ierr = ZOLTAN_MEMERR;
goto End;
}
}
End:
if (ierr == ZOLTAN_OK) {
if (old->indices_to) ZOLTAN_FREE(&(old->indices_to));
if (old->sizes) ZOLTAN_FREE(&(old->sizes));
if (old->sizes_to) ZOLTAN_FREE(&(old->sizes_to));
if (old->sizes_from) ZOLTAN_FREE(&(old->sizes_from));
if (old->starts_to_ptr) ZOLTAN_FREE(&(old->starts_to_ptr));
if (old->starts_from_ptr) ZOLTAN_FREE(&(old->starts_from_ptr));
if (old->indices_to_ptr) ZOLTAN_FREE(&(old->indices_to_ptr));
if (old->indices_from_ptr) ZOLTAN_FREE(&(old->indices_from_ptr));
if (old->request) ZOLTAN_FREE(&(old->request));
if (old->status) ZOLTAN_FREE(&(old->status));
ZOLTAN_FREE(&old);
*plan = new;
}
else {
if (new) {
ZOLTAN_FREE(&(new->request));
ZOLTAN_FREE(&(new->status));
ZOLTAN_FREE(&new);
}
}
return (ierr);
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,316 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <mpi.h>
#include "comm.h"
#include "zoltan_mem.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
int Zoltan_Comm_Resize(
ZOLTAN_COMM_OBJ *plan, /* communication plan object */
int *sizes, /* size of each item I'm sending */
int tag, /* message tag I can use */
int *sum_recv_sizes) /* sum of the sizes of the items I'll receive */
{
int return_flag; /* returned error code */
int my_proc; /* my processor ID */
int nsends, nrecvs; /* number of msgs I'll send & recv */
int self_msg; /* do I have data for myself? */
int sum; /* running total of item sizes */
int *offset = NULL; /* address of each item in send array */
int *index = NULL; /* indices into start_from_ptr */
int *sort_val = NULL; /* start_from to order properly */
int *sizes_to = NULL; /* size of each msg to send (if items vary) */
int *sizes_from = NULL;/* size of each msg to recv (if items vary) */
int *starts_to_ptr = NULL; /* where in dense vector sends start */
int *starts_from_ptr = NULL; /* where in dense vector recvs start */
int *indices_to_ptr = NULL; /* where to find items I send */
/* ordered like procs_to */
int *indices_from_ptr = NULL; /* where to find items I recv */
/* ordered like procs_from */
int var_sizes; /* items have variable sizes? */
int i, j, k; /* loop counters */
static char *yo = "Zoltan_Comm_Resize";
/* If sizes vary, then I need to compute and communicate message lengths */
/* First check if sizes array is NULL on all procs. */
MPI_Comm_rank(plan->comm, &my_proc);
i = (sizes != NULL);
MPI_Allreduce(&i, &var_sizes, 1, MPI_INT, MPI_LOR, plan->comm);
if (var_sizes && plan->indices_from != NULL) {
/* Can't do w/o individual item sizes */
ZOLTAN_COMM_ERROR("Non-blocked, variable-sized recvs not supported", yo, my_proc);
return(ZOLTAN_FATAL);
}
ZOLTAN_FREE(&plan->sizes);
ZOLTAN_FREE(&plan->sizes_to);
ZOLTAN_FREE(&plan->sizes_from);
ZOLTAN_FREE(&plan->starts_to_ptr);
ZOLTAN_FREE(&plan->starts_from_ptr);
ZOLTAN_FREE(&plan->indices_to_ptr);
ZOLTAN_FREE(&plan->indices_from_ptr);
nsends = plan->nsends;
nrecvs = plan->nrecvs;
self_msg = plan->self_msg;
if (!var_sizes) { /* Easy case. Size = length */
plan->total_recv_size = 0;
for (i = 0; i < nrecvs + self_msg; i++) {
plan->total_recv_size += plan->lengths_from[i];
}
plan->max_send_size = 0;
for (i = 0; i < nsends + self_msg; i++) {
if (plan->procs_to[i] != my_proc &&
plan->lengths_to[i] > plan->max_send_size) {
plan->max_send_size = plan->lengths_to[i];
}
}
return_flag = ZOLTAN_OK;
}
else { /* Need to actually compute message sizes */
plan->sizes = (int *) ZOLTAN_MALLOC((plan->nvals + 1) * sizeof(int));
if (plan->sizes == NULL) {
return_flag = ZOLTAN_MEMERR;
goto Mem_Err;
}
for (i = 0; i < plan->nvals; i++) plan->sizes[i] = sizes[i];
return_flag = ZOLTAN_OK;
sizes_to = (int *) ZOLTAN_MALLOC((nsends + self_msg) * sizeof(int));
if (sizes_to == NULL && (nsends + self_msg) != 0) {
return_flag = ZOLTAN_MEMERR;
goto Mem_Err;
}
sizes_from = (int *) ZOLTAN_MALLOC((nrecvs + self_msg) * sizeof(int));
if (sizes_from == NULL && (nrecvs + self_msg) != 0) {
return_flag = ZOLTAN_MEMERR;
goto Mem_Err;
}
for (i = 0; i < nsends + self_msg; i++)
sizes_to[i] = 0;
/* Several cases:
1. indices_to == NULL
=> starts_to != NULL, need to allocate, set starts_to_ptr
2. indices_to != NULL (=> starts_to == NULL)
need to allocate, set indices_to_ptr
3,4. mirror cases for _from
*/
starts_to_ptr = (int *) ZOLTAN_MALLOC((nsends + self_msg) * sizeof(int));
if (starts_to_ptr == NULL && (nsends + self_msg) != 0) {
return_flag = ZOLTAN_MEMERR;
goto Mem_Err;
}
if (plan->indices_to == NULL) {
/* Simpler case; sends already blocked by processor */
index = (int *) ZOLTAN_MALLOC((nsends + self_msg) * sizeof(int));
sort_val = (int *) ZOLTAN_MALLOC((nsends + self_msg) * sizeof(int));
if ((index == NULL || sort_val == NULL) && nsends + self_msg > 0) {
return_flag = ZOLTAN_MEMERR;
goto Mem_Err;
}
for (i = 0; i < nsends + self_msg; i++) {
j = plan->starts_to[i];
for (k = 0; k < plan->lengths_to[i]; k++) {
sizes_to[i] += sizes[j++];
}
if (sizes_to[i] > plan->max_send_size &&
plan->procs_to[i] != my_proc)
plan->max_send_size = sizes_to[i];
}
for (i = 0; i < nsends + self_msg; i++) {
sort_val[i] = plan->starts_to[i];
index[i] = i;
}
Zoltan_Comm_Sort_Ints(sort_val, index, nsends + self_msg);
sum = 0;
for (i = 0; i < nsends + self_msg; i++) {
starts_to_ptr[index[i]] = sum;
sum += sizes_to[index[i]];
}
ZOLTAN_FREE(&index);
ZOLTAN_FREE(&sort_val);
}
else { /* Harder case, sends not blocked */
offset = (int *) ZOLTAN_MALLOC(plan->nvals * sizeof(int));
indices_to_ptr = (int *) ZOLTAN_MALLOC(plan->nvals * sizeof(int));
if ((offset == NULL || indices_to_ptr == NULL) && plan->nvals != 0) {
return_flag = ZOLTAN_MEMERR;
goto Mem_Err;
}
/* Compute address for every item in send array */
sum = 0;
for (i = 0; i < plan->nvals; i++) {
offset[i] = sum;
sum += sizes[i];
}
sum = 0;
plan->max_send_size = 0;
for (i = 0; i < nsends + self_msg; i++) {
starts_to_ptr[i] = sum;
j = plan->starts_to[i];
for (k = 0; k < plan->lengths_to[i]; k++) {
indices_to_ptr[j] = offset[plan->indices_to[j]];
sizes_to[i] += sizes[plan->indices_to[j++]];
}
if (sizes_to[i] > plan->max_send_size &&
plan->procs_to[i] != my_proc)
plan->max_send_size = sizes_to[i];
sum += sizes_to[i];
}
ZOLTAN_FREE(&offset);
}
/* Note: This routine only gets message sizes, not object sizes. */
/* Anything requiring item sizes requires more code */
/* Should such functionality reside here? */
Zoltan_Comm_Exchange_Sizes(sizes_to, plan->procs_to, nsends, self_msg,
sizes_from, plan->procs_from, nrecvs,
&plan->total_recv_size, my_proc, tag, plan->comm);
starts_from_ptr = (int *) ZOLTAN_MALLOC((nrecvs + self_msg) * sizeof(int));
if (starts_from_ptr == NULL && (nrecvs + self_msg) != 0) {
return_flag = ZOLTAN_MEMERR;
goto Mem_Err;
}
if (plan->indices_from == NULL) {
/* Simpler case; recvs already blocked by processor */
/* Harder case currently excluded at top of file */
index = (int *) ZOLTAN_MALLOC((nrecvs + self_msg) * sizeof(int));
sort_val = (int *) ZOLTAN_MALLOC((nrecvs + self_msg) * sizeof(int));
if ((index == NULL || sort_val == NULL) && nrecvs + self_msg > 0) {
return_flag = ZOLTAN_MEMERR;
goto Mem_Err;
}
for (i = 0; i < nrecvs + self_msg; i++) {
sort_val[i] = plan->starts_from[i];
index[i] = i;
}
Zoltan_Comm_Sort_Ints(sort_val, index, nrecvs + self_msg);
sum = 0;
for (i = 0; i < nrecvs + self_msg; i++) {
starts_from_ptr[index[i]] = sum;
sum += sizes_from[index[i]];
}
ZOLTAN_FREE(&index);
ZOLTAN_FREE(&sort_val);
}
/*else {*/ /* Harder case, recvs not blocked */
/* Not currently supported */
/* Can't do w/o individual item sizes */
/* Currently checked for at top of file */
/*}*/
}
Mem_Err:
if (return_flag == ZOLTAN_MEMERR) {
ZOLTAN_FREE(&index);
ZOLTAN_FREE(&sort_val);
ZOLTAN_FREE(&offset);
ZOLTAN_FREE(&plan->sizes);
ZOLTAN_FREE(&plan->sizes_to);
ZOLTAN_FREE(&plan->sizes_from);
ZOLTAN_FREE(&plan->starts_to_ptr);
ZOLTAN_FREE(&plan->starts_from_ptr);
ZOLTAN_FREE(&plan->indices_to_ptr);
ZOLTAN_FREE(&plan->indices_from_ptr);
}
plan->sizes_to = sizes_to;
plan->sizes_from = sizes_from;
plan->starts_to_ptr = starts_to_ptr;
plan->starts_from_ptr = starts_from_ptr;
plan->indices_to_ptr = indices_to_ptr;
plan->indices_from_ptr = indices_from_ptr;
if (sum_recv_sizes)
*sum_recv_sizes = plan->total_recv_size;
return(return_flag);
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,124 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <string.h>
#include "comm.h"
#include "zoltan_mem.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* Given a list of processors & message data, sort them by proc ID */
/* This routine will ensure that the ordering produced by the invert_map */
/* routines is deterministic. This should make bugs more reproducible. */
/* This is a distribution count sort (Knuth) */
/* An easily fixed assumption is that the smallest integer is zero! */
int Zoltan_Comm_Sort_Ints(
int *vals_sort, /* values to be sorted */
int *vals_other, /* other array to be reordered w/ sort */
int nvals) /* length of these two arrays */
{
int *store=NULL, *copy_sort=NULL, *copy_other=NULL, *p;
int i;
int top; /* largest integer to sort, smallest is 0 by assumption */
int err = ZOLTAN_OK;
int already_sorted = 1; /* flag indicating whether vals_sort is
already sorted; can exit early and skip
memory allocations if it is. */
if (nvals < 1 || vals_sort == NULL || vals_other == NULL)
return ZOLTAN_FATAL;
if (nvals == 1)
return ZOLTAN_OK; /* fastest way to sort 1 item is to return */
/* find largest value (sort sometimes used for non processor lists) */
top = vals_sort[0];
for (i = 1; i < nvals; i++) {
if (vals_sort[i-1] > vals_sort[i]) already_sorted = 0;
if (top < vals_sort[i]) top = vals_sort[i];
}
if (already_sorted)
return ZOLTAN_OK;
store = (int*) ZOLTAN_CALLOC (top+2, sizeof(int));
copy_sort = (int*) ZOLTAN_MALLOC (nvals * sizeof(int));
copy_other = (int*) ZOLTAN_MALLOC (nvals * sizeof(int));
if (store && copy_sort && copy_other) {
memcpy (copy_sort, vals_sort, nvals * sizeof(int));
memcpy (copy_other, vals_other, nvals * sizeof(int));
p = store+1;
for (i = 0; i < nvals; i++)
p[copy_sort[i]]++; /* count number of occurances */
for (i = 1; i < top+1; i++)
p[i] += p[i-1]; /* compute partial sums */
/* assert: p[top] = nvals */
p = store; /* effectively shifts down by one */
for (i = 0; i < nvals; i++) {
vals_sort [p[copy_sort [i]]] = copy_sort [i];
vals_other [p[copy_sort [i]]] = copy_other[i];
++p[copy_sort [i]];
}
}
else
err = ZOLTAN_MEMERR;
Zoltan_Multifree (__FILE__, __LINE__, 3, &copy_sort, &copy_other, &store);
return err;
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,257 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <stdlib.h>
#include "zoltan_dd_const.h"
#include "zoltan_align.h"
#include "zz_hash.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* NOTE: See file, README, for associated documentation. (RTH) */
/* Zoltan_DD_Create assumes the global object being managed by the
* directory is a Zoltan global ID, which is a ZOLTAN_ID_TYPE-tuple.
* The "num_gid" parameter is where we specify how many ZOLTAN_ID_TYPEs
* are in the object (zz->Num_GID).
*
* However, some Zoltan code uses a data directory to manage other
* global integer values. When the ZOLTAN_ID_TYPE was always be an
* unsigned integer, that worked.
*
* But now that the ZOLTAN_ID_TYPE can be specified at compile time,
* we need to be more careful.
*
* If the global value is not a Zoltan global ID, then the "num_gid"
* parameter should be factor which, when multiplied by a ZOLTAN_ID_TYPE,
* give an object of the same length as the global value.
*
* So if ZOLTAN_ID_TYPE is a 32-bit int, and the global value being
* managed by the data directory is a 64-bit int, "num_gid" should
* be "2".
*
* The "num_lid" parameter specifies the number ZOLTAN_ID_TYPEs in
* the local ID.
*
* The "user_length" parameter specifies the number of chars in the
* user data.
*/
/******************* Zoltan_DD_Create() ***************************/
int Zoltan_DD_Create (
Zoltan_DD_Directory **dd, /* contains directory state and pointers */
MPI_Comm comm, /* Dup'ed and saved for future use */
int num_gid, /* Number of entries in a global ID. */
int num_lid, /* Number of entries in a local ID.
If zero, ignore LIDs */
int user_length, /* Optional user data length in chars, 0 ignore */
int table_length, /* sizeof hash table, use default if 0 */
int debug_level /* control actions to errors, normally 0 */
)
{
int size, i;
int my_proc;
int array[3], max_array[3], min_array[3];
char *yo = "Zoltan_DD_Create";
if (MPI_Comm_rank(comm, &my_proc) != MPI_SUCCESS) {
ZOLTAN_PRINT_ERROR (-1, yo, "MPI_Comm_rank failed");
return ZOLTAN_FATAL;
}
/* input sanity check */
if (dd == NULL || num_gid < 1 || table_length < 0 || num_lid < 0) {
ZOLTAN_PRINT_ERROR (my_proc, yo, "Invalid input argument");
return ZOLTAN_FATAL;
}
if (debug_level > 4)
ZOLTAN_TRACE_IN (my_proc, yo, NULL);
/* insure all processors are using the same GID, LID, USER lengths */
array[0] = num_gid;
array[1] = num_lid;
array[2] = user_length;
MPI_Allreduce (array, max_array, 3, MPI_INT, MPI_MAX, comm);
MPI_Allreduce (array, min_array, 3, MPI_INT, MPI_MIN, comm);
if (max_array[0] != min_array[0] || max_array[1] != min_array[1]
|| max_array[2] != min_array[2]) {
ZOLTAN_PRINT_ERROR(-1,yo,"LID, GID, USER data lengths differ globally");
return ZOLTAN_FATAL;
}
/* malloc memory for the directory structure + hash table */
size = (table_length) ? table_length: ZOLTAN_DD_HASH_TABLE_COUNT;
size = Zoltan_Recommended_Hash_Size(size);
*dd = (Zoltan_DD_Directory*) ZOLTAN_MALLOC (sizeof (Zoltan_DD_Directory)
+ size * sizeof(DD_NodeIdx));
if (*dd == NULL) {
ZOLTAN_PRINT_ERROR (my_proc, yo, "Can not malloc hash table");
if (debug_level > 4)
ZOLTAN_TRACE_OUT(my_proc, yo, NULL);
return ZOLTAN_MEMERR;
}
/* NULL heads of link list in hash table */
for (i = 0; i < size; i++) (*dd)->table[i] = -1; /* NULL values */
(*dd)->nodecnt = 0;
(*dd)->nodelist = NULL;
(*dd)->nodedata = NULL;
(*dd)->nodelistlen = 0;
(*dd)->nextfreenode = -1;
/* save useful constants into directory for convenience */
(*dd)->debug_level = debug_level; /* [0,3], default 0 */
(*dd)->gid_length = num_gid; /* saved input Num_GID */
(*dd)->lid_length = num_lid; /* saved input Num_LIB */
(*dd)->table_length = size; /* # of linked list heads */
(*dd)->user_data_length = user_length; /* optional user data length */
(*dd)->hash = Zoltan_DD_Hash2;/* default hash algorithm */
(*dd)->hashdata = NULL; /* no hash data */
(*dd)->hashfn = NULL; /* no hash function */
(*dd)->cleanup = NULL; /* user registered cleanup */
(*dd)->max_id_length = (num_gid > num_lid) ? num_gid : num_lid;
/* frequently used dynamic allocation computed sizes */
size = ((num_gid + num_lid) * sizeof(ZOLTAN_ID_TYPE)) + user_length;
(*dd)->nodedata_size = size;
(*dd)->update_msg_size = size + sizeof(DD_Update_Msg);
size = num_gid * sizeof(ZOLTAN_ID_TYPE);
(*dd)->remove_msg_size = size + sizeof(DD_Remove_Msg);
size = user_length + ((*dd)->max_id_length * sizeof(ZOLTAN_ID_TYPE));
(*dd)->find_msg_size = size + sizeof(DD_Find_Msg);
/* force alignment */
(*dd)->nodedata_size = Zoltan_Align_size_t((*dd)->nodedata_size);
(*dd)->update_msg_size = Zoltan_Align_size_t((*dd)->update_msg_size);
(*dd)->remove_msg_size = Zoltan_Align_size_t((*dd)->remove_msg_size);
(*dd)->find_msg_size = Zoltan_Align_size_t((*dd)->find_msg_size);
/* duplicate MPI comm to prevent future comm changes from disrupting */
/* directory communications & save the associated comm size & rank */
if (MPI_Comm_dup (comm, &((*dd)->comm)) != MPI_SUCCESS
|| MPI_Comm_size (comm, &((*dd)->nproc)) != MPI_SUCCESS
|| MPI_Comm_rank (comm, &((*dd)->my_proc)) != MPI_SUCCESS) {
ZOLTAN_PRINT_ERROR (my_proc, yo, "MPI Problem, unable to continue");
return ZOLTAN_FATAL;
}
if (debug_level > 4)
ZOLTAN_TRACE_OUT (my_proc, yo, NULL);
return ZOLTAN_OK;
}
/******************* Copy functions ***************************/
Zoltan_DD_Directory *Zoltan_DD_Copy(Zoltan_DD_Directory *from)
{
Zoltan_DD_Directory *to = NULL;
Zoltan_DD_Copy_To(&to, from);
return to;
}
int Zoltan_DD_Copy_To(Zoltan_DD_Directory **toptr, Zoltan_DD_Directory *from)
{
static char *yo = "Zoltan_DD_Copy_To";
Zoltan_DD_Directory *to= NULL;
if (!toptr) {
return ZOLTAN_FATAL;
}
if (*toptr) {
Zoltan_DD_Destroy(toptr);
}
if (from) {
DD_NodeIdx i;
to = *toptr =
(Zoltan_DD_Directory *)ZOLTAN_MALLOC(
sizeof (Zoltan_DD_Directory) +
(from->table_length * sizeof(DD_NodeIdx)));
if (!to) {
ZOLTAN_PRINT_ERROR(from->my_proc, yo, "Insufficient memory.");
return ZOLTAN_MEMERR;
}
*to = *from;
memcpy(to->table, from->table, to->table_length * sizeof(DD_NodeIdx));
MPI_Comm_dup(from->comm, &(to->comm));
if (to->nodelistlen) {
to->nodelist = (DD_Node *) ZOLTAN_MALLOC(to->nodelistlen * sizeof(DD_Node));
memcpy(to->nodelist, from->nodelist, to->nodelistlen * sizeof(DD_Node));
to->nodedata = (char *) ZOLTAN_MALLOC(to->nodelistlen * to->nodedata_size);
memcpy(to->nodedata, from->nodedata, to->nodelistlen * to->nodedata_size);
for (i = 0; i < to->nodelistlen; i++) {
to->nodelist[i].gid = (ZOLTAN_ID_PTR)(to->nodedata + i*to->nodedata_size);
}
}
}
return ZOLTAN_OK;
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,93 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <stdlib.h>
#include "zoltan_dd_const.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/********************** Zoltan_DD_Destroy() *********************/
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;
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,337 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <stdlib.h>
#include "zoltan_dd_const.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
int Zoltan_DD_GetLocalKeys(Zoltan_DD_Directory *dd,
ZOLTAN_ID_PTR *gid,
int *size)
{
int ierr = ZOLTAN_OK;
int i, k;
DD_NodeIdx nodeidx;
DD_Node *ptr;
int gid_alloc_size;
gid_alloc_size = dd->table_length;
(*gid) = (ZOLTAN_ID_PTR)ZOLTAN_MALLOC(
gid_alloc_size*dd->gid_length*sizeof(ZOLTAN_ID_TYPE));
k= 0;
for (i = 0; i < dd->table_length; i++)
for (nodeidx = dd->table[i]; nodeidx != -1;
nodeidx = dd->nodelist[nodeidx].next) {
ptr = dd->nodelist + nodeidx;
if (k >= gid_alloc_size) {
gid_alloc_size *= 2;
(*gid) = (ZOLTAN_ID_PTR)
ZOLTAN_REALLOC((*gid),
gid_alloc_size*dd->gid_length*sizeof(ZOLTAN_ID_TYPE));
}
ZOLTAN_SET_ID (dd->gid_length, (*gid)+k*dd->gid_length, ptr->gid);
k++;
}
(*size) = k;
return (ierr);
}
/* NOTE: See file, README, for associated documentation. (RTH) */
static int DD_Find_Local (Zoltan_DD_Directory *dd, ZOLTAN_ID_PTR gid,
ZOLTAN_ID_PTR lid, char *user, int *partition, int *owner) ;
/******************** Zoltan_DD_Find() **************************/
int Zoltan_DD_Find (
Zoltan_DD_Directory *dd, /* contains directory state information */
ZOLTAN_ID_PTR gid, /* Incoming list of GIDs to get owners proc */
ZOLTAN_ID_PTR lid, /* Outgoing corresponding list of LIDs */
char *data, /* Outgoing optional corresponding user data */
int *partition, /* Outgoing optional partition information */
int count, /* Count of GIDs in above list (in) */
int *owner) /* Outgoing optional list of data owners */
{
ZOLTAN_COMM_OBJ *plan = NULL; /* efficient MPI communication */
char *rbuff = NULL; /* receive buffer */
char *rbufftmp = NULL; /* pointer into receive buffer */
char *sbuff = NULL; /* send buffer */
char *sbufftmp = NULL; /* pointer into send buffer */
int *procs = NULL; /* list of processors to contact */
DD_Find_Msg *ptr = NULL;
int i;
int nrec; /* number of messages to receive */
int err = ZOLTAN_OK; /* return error condition */
int errcount; /* count of GIDs not found */
char *yo = "Zoltan_DD_Find";
/* input sanity check */
if (dd == NULL || count < 0 || (gid == NULL && count > 0)) {
ZOLTAN_PRINT_ERROR (dd ? dd->my_proc : ZOLTAN_DD_NO_PROC, yo,
"Invalid input argument");
return ZOLTAN_FATAL;
}
if (dd->debug_level > 4)
ZOLTAN_TRACE_IN(dd->my_proc, yo, NULL);
/* allocate memory for processors to contact for directory info */
if (count) {
procs = (int*) ZOLTAN_MALLOC (sizeof(int) * count);
if (procs == NULL) {
ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc proc list");
if (dd->debug_level > 4)
ZOLTAN_TRACE_OUT(dd->my_proc, yo, NULL);
return ZOLTAN_MEMERR;
}
}
/* allocate memory for DD_Find_Msg send buffer */
if (count) {
sbuff = (char*) ZOLTAN_CALLOC (count, dd->find_msg_size);
if (sbuff == NULL) {
ZOLTAN_FREE (&procs);
ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc send buffer");
if (dd->debug_level > 4)
ZOLTAN_TRACE_OUT(dd->my_proc, yo, NULL);
return ZOLTAN_MEMERR;
}
}
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After mallocs");
/* for each GID, fill DD_Find_Msg buffer and contact list */
sbufftmp = sbuff;
for (i = 0; i < count; i++) {
procs[i] = dd->hash (gid + i*dd->gid_length, dd->gid_length, dd->nproc,
dd->hashdata, dd->hashfn);
ptr = (DD_Find_Msg*) sbufftmp;
sbufftmp += dd->find_msg_size;
ptr->index = i;
ptr->proc = procs[i];
ZOLTAN_SET_ID (dd->gid_length, ptr->id, gid + i*dd->gid_length);
}
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After fill");
/* create efficient communication plan */
err = Zoltan_Comm_Create (&plan, count, procs, dd->comm,
ZOLTAN_DD_FIND_MSG_TAG, &nrec);
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Comm_Create");
if (err != ZOLTAN_OK)
goto fini;
/* allocate receive buffer */
if (nrec) {
rbuff = (char*) ZOLTAN_MALLOC ((size_t)nrec*(size_t)(dd->find_msg_size));
if (rbuff == NULL) {
err = ZOLTAN_MEMERR;
goto fini;
}
}
/* send out find messages across entire system */
err = Zoltan_Comm_Do (plan, ZOLTAN_DD_FIND_MSG_TAG+1, sbuff,
dd->find_msg_size, rbuff);
if (err != ZOLTAN_OK)
goto fini;
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Comm_Do");
/* get find messages directed to me, fill in return information */
errcount = 0;
rbufftmp = rbuff;
for (i = 0; i < nrec; i++) {
ptr = (DD_Find_Msg*) rbufftmp;
rbufftmp += dd->find_msg_size;
err = DD_Find_Local (dd, ptr->id, ptr->id,
(char *)(ptr->id + dd->max_id_length),
&ptr->partition, &ptr->proc);
if (err == ZOLTAN_WARN)
++errcount;
}
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After fill in return info");
/* send return information back to requester */
err = Zoltan_Comm_Do_Reverse(plan, ZOLTAN_DD_FIND_MSG_TAG+2, rbuff,
dd->find_msg_size, NULL, sbuff);
if (err != ZOLTAN_OK)
goto fini;
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Comm_Reverse");
/* fill in user supplied lists with returned information */
sbufftmp = sbuff;
for (i = 0; i < count; i++) {
ptr = (DD_Find_Msg*) sbufftmp;
sbufftmp += dd->find_msg_size;
if (owner)
owner[ptr->index] = ptr->proc;
if (partition)
partition[ptr->index] = ptr->partition ;
if (lid)
ZOLTAN_SET_ID(dd->lid_length,lid+ptr->index*dd->lid_length,ptr->id);
if (data)
memcpy(data + (size_t)(ptr->index) * (size_t)(dd->user_data_length),
ptr->id + dd->max_id_length, dd->user_data_length);
}
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After fill return lists");
/* err = ZOLTAN_OK; */
MPI_Allreduce(&errcount, &err, 1, MPI_INT, MPI_SUM, dd->comm);
err = (err) ? ZOLTAN_WARN : ZOLTAN_OK;
/* if at least one GID was not found, potentially notify caller of error */
if (dd->debug_level > 0) {
char str[100]; /* diagnostic message string */
sprintf (str, "Processed %d GIDs, GIDs not found: %d", count, errcount);
ZOLTAN_PRINT_INFO (dd->my_proc, yo, str);
}
fini:
ZOLTAN_FREE (&sbuff);
ZOLTAN_FREE (&rbuff);
ZOLTAN_FREE (&procs) ;
Zoltan_Comm_Destroy (&plan);
if (dd->debug_level > 4)
ZOLTAN_TRACE_OUT(dd->my_proc, yo, NULL);
return err;
}
/****************** DD_Find_Local() ***************************/
/* For a given gid, DD_Find_Local() provides its local ID, owner, optional
* user data, and partition from the local distributed directory. An error
* is returned if the gid is not found.
*/
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;
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,163 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <stdlib.h>
#include "zoltan_dd_const.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* NOTE: See file, README, for associated documentation. (RTH) */
/*****************************************************************************/
/* DD_Hash2 is a hash function for Zoltan ids (local or global).
* It is derived from Zoltan_Hash.
*
* Input:
* key: a key to hash of type ZOLTAN_ID_PTR
* num_id_entries: the number of (ZOLTAN_ID_TYPE-sized) entries of
* the key to use
* n: the range of the hash function is 0..n-1
*
* Return value:
* the hash value, an unsigned integer between 0 and n-1
*/
#define ZZ_MURMUR_HASH
#ifdef ZZ_MURMUR_HASH
#include "murmur3.c"
unsigned int Zoltan_DD_Hash2(ZOLTAN_ID_PTR key, int num_id_entries,
unsigned int n,
void *hashdata, ZOLTAN_HASH_FN *fn)
{
/*
* Algorithm:
* Murmurhash3 as in Zoltan_Hash, with a different seed value.
* MurmurHash3 was written by Austin Appleby, and is placed in the
* public domain. The author hereby disclaims copyright to this source
* code.
*/
uint32_t k;
MurmurHash3_x86_32((void *)key, sizeof(ZOLTAN_ID_TYPE)*num_id_entries,
14, (void *)&k);
return(k % n);
}
#endif /* ZZ_MURMUR_HASH */
#ifdef ZZ_KNUTH_HASH
#define ZOLTAN_DD_HASH_CONSTANT 2654435761U /* consider 516595003U */
unsigned int Zoltan_DD_Hash2(ZOLTAN_ID_PTR key, int num_id_entries,
unsigned int n,
void *hashdata, ZOLTAN_HASH_FN *fn)
{
/*
* Algorithm:
* This hash function is based on Don Knuth's golden ratio
* multiplicative method. Bitwise xor is used for keys
* longer than an int. The method works well for keys
* of size one or two ints, which is typically the case.
*
* This hash function should be replaced with a stronger method
* if good hashing of a large number of keys is important.
*
* Author:
* Erik Boman, eboman@cs.sandia.gov (SNL 9226)
* Replaced explict constant with #define below. Consider changing
* to new constant. Changed name to DD_Hash2. RTH
*/
unsigned int h, rest, *p, bytes, num_bytes;
char *byteptr;
num_bytes = (unsigned int) num_id_entries * sizeof(ZOLTAN_ID_TYPE);
/* First hash the int-sized portions of the key */
h = 0;
for (p = (unsigned int *)key, bytes=num_bytes;
bytes >= (unsigned int) sizeof(int);
bytes-=sizeof(int), p++){
h = (h*ZOLTAN_DD_HASH_CONSTANT) ^ (*p);
}
/* Then take care of the remaining bytes, if any */
rest = 0;
for (byteptr = (char *)p; bytes > 0; bytes--, byteptr++){
rest = (rest<<8) | (*byteptr);
}
/* Merge the two parts */
if (rest)
h = (h*ZOLTAN_DD_HASH_CONSTANT) ^ rest;
/* Return h mod n */
return (h%n);
}
#endif /* ZOLTAN_KNUTH_HASH */
void Zoltan_DD_default_cleanup (void * hashdata)
{
ZOLTAN_FREE(&hashdata);
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,179 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <stdlib.h>
#include "zoltan_dd_const.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/*
* Idea: Store hash table as array of bucket heads, pointing into
* an array-based linked list of nodes (instead of to individually
* allocated nodes).
* The array-based memory would have a free-memory list running
* through it, allowing items to be added to or deleted from the
* directory.
*/
/******************************************************************************/
int DD_Memory_Alloc_Nodelist(
Zoltan_DD_Directory *dd, /* directory state information */
DD_NodeIdx count, /* Number of GIDs in update list */
float overalloc /* Percentage to extra nodes to
allocate (for future dynamic
additions). */
)
{
/* Allocate node memory and initialize it to be all free. */
/* Return error code if memory alloc fails. */
int ierr = ZOLTAN_OK;
DD_Node *ptr;
char *dataptr;
DD_NodeIdx nodeidx;
DD_NodeIdx len = count * (1. + overalloc);
dd->nodelistlen = len;
if (len > 0) {
dd->nodelist = (DD_Node *) ZOLTAN_MALLOC(sizeof(DD_Node) * len);
dd->nodedata = (char *) ZOLTAN_MALLOC(dd->nodedata_size * len);
/* TODO ADD ERROR CHECK */
/* Initialize the freenode list; all nodes are initially free. */
/* Also initialize gid pointers to nodedata. */
dd->nextfreenode = 0;
for (ptr = dd->nodelist, dataptr = dd->nodedata, nodeidx = 0;
nodeidx < len;
nodeidx++, ptr++, dataptr += dd->nodedata_size) {
ptr->next = nodeidx + 1;
ptr->gid = (ZOLTAN_ID_PTR) dataptr;
ptr->free = 1;
}
dd->nodelist[len-1].next = -1; /* NULL value at end of list */
}
dd->nodecnt = 0;
return ierr;
}
/******************************************************************************/
DD_NodeIdx DD_Memory_Alloc_Node(Zoltan_DD_Directory *dd)
{
/* "allocate" a node by removing it from the free list and returning
* its NodeIdx.
*/
DD_NodeIdx returnnode;
if (dd->nextfreenode == -1) {
/* No more room for new nodes in the node list.
* Realloc memory and set up a new freelist.
*/
DD_NodeIdx newlen = dd->nodelistlen * 2;
DD_NodeIdx nodeidx;
DD_Node *ptr;
char *dataptr;
dd->nodelist = (DD_Node *) ZOLTAN_REALLOC(dd->nodelist,
sizeof(DD_Node) * newlen);
dd->nodedata = (char *) ZOLTAN_REALLOC(dd->nodedata,
dd->nodedata_size * newlen);
/* TODO ADD ERROR CHECK */
/* Reinitialize the gid pointers in the realloc'ed nodelist. */
for (ptr = dd->nodelist, dataptr = dd->nodedata, nodeidx = 0;
nodeidx < newlen;
ptr++, dataptr += dd->nodedata_size, nodeidx++)
ptr->gid = (ZOLTAN_ID_PTR) dataptr;
/* Initialize free list in the newly extended memory */
dd->nextfreenode = dd->nodelistlen;
for (nodeidx = dd->nodelistlen; nodeidx < newlen-1; nodeidx++) {
dd->nodelist[nodeidx].next = nodeidx+1;
dd->nodelist[nodeidx].free = 1;
}
dd->nodelist[newlen-1].next = -1;
dd->nodelist[newlen-1].free = 1;
dd->nodelistlen = newlen;
}
returnnode = dd->nextfreenode;
dd->nextfreenode = dd->nodelist[returnnode].next;
dd->nodelist[returnnode].next = -1;
dd->nodelist[returnnode].free = 0;
dd->nodecnt++;
return returnnode;
}
/******************************************************************************/
void DD_Memory_Free_Node(
Zoltan_DD_Directory *dd,
DD_NodeIdx freenode
)
{
/* "free" a node by returning it to the free list. */
/* TODO Error check: freenode should be < nodelistlen */
dd->nodelist[freenode].next = dd->nextfreenode;
dd->nodelist[freenode].free = 1;
dd->nextfreenode = freenode;
dd->nodecnt--;
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,69 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef ZOLTAN_DD_MEMORY_H_
#define ZOLTAN_DD_MEMORY_H_
#include <stdio.h>
#include <stdlib.h>
#include "zoltan_dd_const.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
extern int *DD_Memory_Alloc_Nodelist(Zoltan_DD_Directory *, DD_NodeIdx , float);
extern DD_NodeIdx DD_Memory_Alloc_Node(Zoltan_DD_Directory *);
extern void DD_Memory_Free_Node(Zoltan_DD_Directory*, DD_NodeIdx);
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif
#endif

View File

@ -0,0 +1,115 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <stdlib.h>
#include "zoltan_dd_const.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* NOTE: See file, README, for associated documentation. (RTH) */
/******************** Zoltan_DD_Print() ***********************/
int Zoltan_DD_Print (
Zoltan_DD_Directory *dd) /* contains directory state information */
{
int i,j;
DD_NodeIdx nodeidx;
DD_Node *ptr;
char *yo = "Zoltan_DD_Print";
/* input sanity checks */
if (dd == NULL) {
ZOLTAN_PRINT_ERROR (ZOLTAN_DD_NO_PROC, yo, "NULL dd input argument");
return ZOLTAN_FATAL;
}
if (dd->debug_level > 4)
ZOLTAN_TRACE_IN (dd->my_proc, yo, NULL);
/* walk linked list printing each node */
for (i = 0; i < dd->table_length; i++)
for (nodeidx = dd->table[i]; nodeidx != -1;
nodeidx = dd->nodelist[nodeidx].next) {
ptr = dd->nodelist + nodeidx;
printf ("ZOLTAN DD Print(%d): \tList %3d, \tGID ", dd->my_proc, i);
printf("(");
for (j = 0 ; j < dd->gid_length; j++)
printf(ZOLTAN_ID_SPEC " ", ptr->gid[j]);
printf(") ");
if (dd->lid_length > 0) {
printf("\tLID (");
for (j = 0; j < dd->lid_length; j++)
printf( ZOLTAN_ID_SPEC " ", ptr->gid[j+dd->gid_length]);
printf(") ");
}
printf ("\tPart %d\n", ptr->partition);
printf ("\tOwner %d\n", ptr->owner);
}
if (dd->debug_level > 4)
ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL) ;
return ZOLTAN_OK;
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,261 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <stdlib.h>
#include "zoltan_dd_const.h"
#include "DD_Memory.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* NOTE: See file, README, for associated documentation. (RTH) */
static int DD_Remove_Local (Zoltan_DD_Directory *dd, ZOLTAN_ID_PTR gid) ;
/******************** Zoltan_DD_Remove() ***********************/
int Zoltan_DD_Remove (
Zoltan_DD_Directory *dd, /* directory state infomation */
ZOLTAN_ID_PTR gid, /* Incoming list of GIDs to remove */
int count) /* Number of GIDs in removal list */
{
int *procs = NULL; /* list of processors to contact */
DD_Remove_Msg *ptr = NULL;
ZOLTAN_COMM_OBJ *plan = NULL; /* efficient MPI communication */
char *sbuff = NULL; /* send buffer */
char *sbufftmp = NULL;/* pointer into send buffer */
char *rbuff = NULL; /* receive buffer */
char *rbufftmp = NULL;/* pointer into receive buffer */
int nrec; /* number of receives to expect */
int i;
int err; /* error condition to return */
int errcount; /* count of GIDs not found */
char str[100]; /* string to build error messages */
char *yo = "Zoltan_DD_Remove";
/* input sanity checks */
if (dd == NULL || count < 0 || (gid == NULL && count > 0)) {
ZOLTAN_PRINT_ERROR (dd ? dd->my_proc : ZOLTAN_DD_NO_PROC, yo,
"Invalid input argument");
return ZOLTAN_FATAL;
}
if (dd->debug_level > 4)
ZOLTAN_TRACE_IN (dd->my_proc, yo, NULL);
/* allocate memory for processor contact list */
if (count) {
procs = (int*) ZOLTAN_MALLOC (sizeof(int) * count);
if (procs == NULL) {
ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc proc list");
if (dd->debug_level > 4)
ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL);
return ZOLTAN_MEMERR;
}
}
/* allocate memory for DD_Remove_Msg send buffer */
if (count) {
sbuff = (char*)ZOLTAN_MALLOC((size_t)(dd->remove_msg_size)*(size_t)count);
if (sbuff == NULL) {
ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc send buffer");
err = ZOLTAN_MEMERR;
goto fini;
}
}
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO (dd->my_proc, yo, "After proc & sbuff mallocs");
/* for each GID, fill in contact list and then message structure */
sbufftmp = sbuff;
for (i = 0; i < count; i++) {
procs[i] = dd->hash(gid + i*dd->gid_length, dd->gid_length, dd->nproc,
dd->hashdata, dd->hashfn);
ptr = (DD_Remove_Msg*) sbufftmp;
sbufftmp += dd->remove_msg_size;
ptr->owner = dd->my_proc;
ZOLTAN_SET_ID (dd->gid_length, ptr->gid, gid + i * dd->gid_length);
}
/* now create efficient communication plan */
err = Zoltan_Comm_Create (&plan, count, procs, dd->comm,
ZOLTAN_DD_REMOVE_MSG_TAG, &nrec);
if (err != ZOLTAN_OK) {
ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Comm_Create error");
goto fini;
}
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO (dd->my_proc, yo, "After Zoltan_Comm_Create");
/* allocate receive buffer for nrec DD_Remove_Msg structures */
if (nrec) {
rbuff = (char*)ZOLTAN_MALLOC((size_t)nrec*(size_t)(dd->remove_msg_size));
if (rbuff == NULL) {
ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Receive buffer malloc failed");
err = ZOLTAN_MEMERR;
goto fini;
}
}
/* send my remove messages & receive removes directed to me */
err = Zoltan_Comm_Do (plan, ZOLTAN_DD_UPDATE_MSG_TAG+1, sbuff,
dd->remove_msg_size, rbuff);
if (err != ZOLTAN_OK) {
ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Comm_Do error");
goto fini;
}
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO (dd->my_proc, yo, "After Zoltan_Comm_Do");
/* for each message rec'd, remove local directory info */
errcount = 0;
rbufftmp = rbuff;
for (i = 0; i < nrec; i++) {
ptr = (DD_Remove_Msg*) rbufftmp;
rbufftmp += dd->remove_msg_size;
err = DD_Remove_Local (dd, ptr->gid);
if (err == ZOLTAN_WARN)
++errcount;
}
err = ZOLTAN_OK;
if (dd->debug_level) {
sprintf (str, "Processed %d GIDs (%d local), %d GIDs not found",
count, nrec, errcount);
ZOLTAN_PRINT_INFO (dd->my_proc, yo, str);
err = (errcount) ? ZOLTAN_WARN : ZOLTAN_OK;
}
/* done, now free up things and return */
fini:
ZOLTAN_FREE (&procs);
ZOLTAN_FREE (&sbuff);
ZOLTAN_FREE (&rbuff);
Zoltan_Comm_Destroy (&plan);
if (dd->debug_level > 4)
ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL);
return err;
}
/****************** DD_Remove_Local() **************************/
/* The given global ID, gid, is removed from the local distributed
* directory. An error is returned if the gid is not found.
*/
static int DD_Remove_Local (Zoltan_DD_Directory *dd,
ZOLTAN_ID_PTR gid) /* GID to be removed (in) */
{
DD_Node *ptr;
DD_NodeIdx nodeidx, prevnodeidx;
int index;
char *yo = "DD_Remove_Local";
/* input sanity checking */
if (dd == NULL || gid == NULL) {
ZOLTAN_PRINT_ERROR ((dd == NULL) ? ZOLTAN_DD_NO_PROC : dd->my_proc,
yo, "Invalid input argument");
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 linked list until end looking for matching gid (key) */
prevnodeidx = -1;
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) {
/* found node to remove, need to preserve its next ptr */
if (prevnodeidx != -1)
dd->nodelist[prevnodeidx].next = ptr->next;
else
dd->table[index] = ptr->next;
DD_Memory_Free_Node(dd, nodeidx); /* now OK to delete node */
if (dd->debug_level > 5)
ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL);
return ZOLTAN_OK;
}
prevnodeidx = nodeidx;
}
/* We get here only if the global ID has not been found */
if (dd->debug_level > 5)
ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL);
return ZOLTAN_WARN;
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,101 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <stdlib.h>
#include "zoltan_dd_const.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* NOTE: See file, README, for associated documentation. (RTH) */
static unsigned int dd_hash_user (
ZOLTAN_ID_PTR gid, int gid_length,
unsigned int nproc,
void *data,
ZOLTAN_HASH_FN *fn)
{
return (*fn)(gid, gid_length, nproc);
}
/************* Zoltan_DD_Set_Hash_Fn() ***********************/
int Zoltan_DD_Set_Hash_Fn (
Zoltan_DD_Directory *dd, /* directory state information */
ZOLTAN_HASH_FN *hash)
{
char *yo = "Zoltan_DD_Set_Hash_Fn";
/* input sanity checking */
if (dd == NULL || hash == NULL) {
ZOLTAN_PRINT_ERROR (0, yo, "Invalid input argument");
return ZOLTAN_FATAL ;
}
dd->hash = (DD_Hash_fn*)dd_hash_user;
dd->hashdata = NULL;
dd->hashfn = hash;
dd->cleanup = (DD_Cleanup_fn*) NULL;
if (dd->debug_level > 0)
ZOLTAN_PRINT_INFO (dd->my_proc, yo, "Successful");
return ZOLTAN_OK;
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,124 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <stdlib.h>
#include "zoltan_dd_const.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
struct dd_nh1_struct {
int max_gid ;
int groupsize ;
};
static unsigned int dd_nh1 (ZOLTAN_ID_PTR gid, int gid_length,
unsigned int nproc, struct dd_nh1_struct* hashdata, ZOLTAN_HASH_FN *fn) ;
/************* Zoltan_DD_Set_Hash_Fn1() ***********************/
/*
** These routines associate the first n=groupsize GIDs to proc 0, the
** next n to proc 1, etc. It assumes the GIDs are consecutive numbers.
** It assumes that GIDs primarily stay near their original owner. The
** GID length is assumed to be 1. GIDs outside of range are evenly
** distributed among the processors via modulo(nproc).
*/
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_Neighbor_Hash_Fn1";
struct dd_nh1_struct *hashdata;
if (dd == NULL) {
ZOLTAN_PRINT_ERROR (0, yo, "NULL DDirectory pointer");
return ZOLTAN_FATAL;
}
if (size < 1) {
ZOLTAN_PRINT_WARN (0, yo, "Invalid input argument; size < 1");
return ZOLTAN_WARN;
}
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->hashfn = NULL;
dd->hashdata = hashdata;
dd->cleanup = (DD_Cleanup_fn*) &Zoltan_DD_default_cleanup;
hashdata->max_gid = size * dd->nproc; /* larger GIDs out of range */
return ZOLTAN_OK;
}
static unsigned int dd_nh1 (ZOLTAN_ID_PTR gid, int gid_length,
unsigned int nproc, struct dd_nh1_struct* hashdata, ZOLTAN_HASH_FN *fn)
{
int id = (signed) *gid;
return (unsigned int) ((id < hashdata->max_gid) ? (id / hashdata->groupsize)
: (id % (int)nproc));
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,213 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <stdlib.h>
#include "zoltan_dd_const.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
typedef struct
{
int high;
int low;
int proc;
} Range_Info;
struct dd_nh2_struct {
Range_Info *ptr;
int nproc;
int low_limit;
int high_limit;
int debug_level;
int count;
};
static unsigned int dd_nh2 (ZOLTAN_ID_PTR gid, int gid_length,
unsigned int nproc, struct dd_nh2_struct* hashdata, ZOLTAN_HASH_FN *fn);
static int compare_sort (const void *a, const void *b);
static int compare_search (const void *a, const void *b);
static void dd_nh2_cleanup (struct dd_nh2_struct* hashdata);
/************* Zoltan_DD_Set_Hash_Fn2() ***********************/
/*
** These routines allow the user to specify a beginning and ending GID
** (number) per processor to associate an arbitrary GID to its orginal
** owner processor. It assumes the GIDs are consecutive numbers.
** It assumes that GIDs primarily stay near their original owner. It
** requires that the number of high, low, & proc entries is 'n'. It
** assumes the GID length is 1.
*/
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->hashdata = hashdata;
dd->hashfn = NULL;
dd->cleanup = (DD_Cleanup_fn*)&dd_nh2_cleanup;
/* 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;
}
static unsigned int dd_nh2 (ZOLTAN_ID_PTR gid, int gid_length,
unsigned int junk, struct dd_nh2_struct* hashdata, ZOLTAN_HASH_FN *fn)
{
Range_Info *p;
char *yo = "dd_ny2";
int id = (signed) *gid;
/* check if gid is out of range */
if (id > hashdata->high_limit || id < hashdata->low_limit)
return id % hashdata->nproc;
p = (Range_Info*) bsearch (gid, hashdata->ptr, hashdata->count, sizeof (Range_Info),
compare_search);
if (p == NULL) { /* shouldn't happen */
if (hashdata->debug_level > 1)
ZOLTAN_PRINT_ERROR (0, yo, "C function bsearch returned NULL.") ;
return id % hashdata->nproc;
}
return p->proc;
}
static int compare_sort (const void *a, const void *b)
{
if (((Range_Info*) a)->low < ((Range_Info *) b)->low) return -1;
if (((Range_Info*) a)->low > ((Range_Info *) b)->low) return 1;
else return 0 ;
}
static int compare_search (const void *a, const void *b)
{
int temp = (signed) *((ZOLTAN_ID_TYPE *) a);
if (temp < ((Range_Info*) b)->low) return -1;
if (temp > ((Range_Info*) b)->high) return 1;
else return 0 ;
}
static void dd_nh2_cleanup (struct dd_nh2_struct *hashdata)
{
if (hashdata == NULL) return;
ZOLTAN_FREE (&hashdata->ptr);
ZOLTAN_FREE (&hashdata);
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,129 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <stdlib.h>
#include "zoltan_dd_const.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
struct dd_nh3_struct {
int remainder;
int average;
int breakpt;
int total_;};
static unsigned int dd_nh3 (ZOLTAN_ID_PTR gid, int gid_length,
unsigned int nproc, struct dd_nh3_struct* hashdata, ZOLTAN_HASH_FN *);
/************* Zoltan_DD_Set_Hash_Fn3() ***********************/
/*
** These routines associate the first n=groupsize GIDs to proc 0, the
** next n to proc 1, etc. It assumes the GIDs are consecutive numbers.
** It assumes that GIDs primarily stay near their original owner. The
** GID length is assumed to be 1. GIDs outside of range are evenly
** distributed among the processors via modulo(nproc). This method
** is designed for Trilinos/Epetra linear map.
*/
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->hashfn = NULL;
dd->cleanup = (DD_Cleanup_fn*)&Zoltan_DD_default_cleanup;
return ZOLTAN_OK;
}
static unsigned int dd_nh3 (ZOLTAN_ID_PTR gid, int gid_length,
unsigned int nproc, struct dd_nh3_struct * hashdata, ZOLTAN_HASH_FN *fn)
{
int id = (signed) *gid;
if (id < hashdata->breakpt)
return id/(hashdata->average+1);
if (id < hashdata->total_)
return hashdata->remainder + (id-hashdata->breakpt)/hashdata->average;
return 0; /* error, gid is out of range */
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,124 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <stdlib.h>
#include "zoltan_dd_const.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* NOTE: See file, README, for associated documentation. (RTH) */
/******************* Zoltan_DD_Stats() ***************************/
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_NodeIdx nodeidx;
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] != -1)
list_count++; /* count of distict linked lists */
for (nodeidx = dd->table[i]; nodeidx != -1;
nodeidx = dd->nodelist[nodeidx].next) {
ptr = dd->nodelist + nodeidx;
if (dd->debug_level > 6) {
sprintf(str, "GID " ZOLTAN_ID_SPEC ", 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);
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,358 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <stdio.h>
#include <stdlib.h>
#include "zoltan_dd_const.h"
#include "DD_Memory.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
static int DD_Update_Local (Zoltan_DD_Directory *dd, ZOLTAN_ID_PTR gid,
ZOLTAN_ID_PTR lid, char *user, int partition, int owner);
/****************** Zoltan_DD_Update() *************************/
int Zoltan_DD_Update (
Zoltan_DD_Directory *dd, /* directory state information */
ZOLTAN_ID_PTR gid, /* Incoming list of GIDs to update */
ZOLTAN_ID_PTR lid, /* Incoming corresponding LIDs (optional) */
char *user, /* Incoming list of user data (optional) */
int *partition, /* Optional, grouping of GIDs to partitions */
int count) /* Number of GIDs in update list */
{
int *procs = NULL; /* list of processors to contact */
DD_Update_Msg *ptr = NULL;
ZOLTAN_COMM_OBJ *plan = NULL; /* for efficient MPI communication */
char *sbuff = NULL; /* send buffer */
char *sbufftmp = NULL;/* pointer into send buffer */
char *rbuff = NULL; /* receive buffer */
char *rbufftmp = NULL;/* pointer into receive buffer */
int nrec = 0; /* number of receives to expect */
int i;
int err;
int errcount = 0; /* count of GIDs not found, added */
char str[100]; /* build error message string */
char *yo = "Zoltan_DD_Update";
/* input sanity checking */
if (dd == NULL || count < 0 || (gid == NULL && count > 0)) {
ZOLTAN_PRINT_ERROR ((dd == NULL ? ZOLTAN_DD_NO_PROC : dd->my_proc), yo,
"Invalid input argument");
return ZOLTAN_FATAL;
}
if (dd->debug_level > 4)
ZOLTAN_TRACE_IN(dd->my_proc, yo, NULL);
/* part of initializing the error checking process */
/* for each linked list head, walk its list resetting errcheck */
if (dd->debug_level)
for (i = 0; i < dd->table_length; i++) {
DD_NodeIdx nodeidx;
for (nodeidx = dd->table[i]; nodeidx != -1;
nodeidx = dd->nodelist[nodeidx].next)
dd->nodelist[nodeidx].errcheck = ZOLTAN_DD_NO_PROC;
}
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After reset errcheck");
/* allocate memory for list of processors to contact */
if (count) {
procs = (int*) ZOLTAN_MALLOC (sizeof(int) * count);
if (procs == NULL) {
ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc proc list");
err = ZOLTAN_MEMERR;
goto fini;
}
}
/* allocate memory for DD_Update_Msg send buffer */
if (count) {
sbuff = (char*) ZOLTAN_CALLOC (count, dd->update_msg_size);
if (sbuff == NULL) {
ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc send buffer");
err = ZOLTAN_MEMERR;
goto fini;
}
}
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After mallocs");
/* for each GID given, fill in contact list and then message structure */
sbufftmp = sbuff;
for (i = 0; i < count; i++) {
procs[i] = dd->hash(gid + i*dd->gid_length, dd->gid_length, dd->nproc,
dd->hashdata, dd->hashfn);
ptr = (DD_Update_Msg*) sbufftmp;
sbufftmp += dd->update_msg_size;
ptr->lid_flag = (lid) ? 1 : 0;
ptr->user_flag = (user) ? 1 : 0;
ptr->partition_flag = (partition) ? 1 : 0;
ptr->partition = (partition) ? *(partition + i) : -1;
ptr->owner = dd->my_proc;
ZOLTAN_SET_ID (dd->gid_length, ptr->gid, gid + i * dd->gid_length);
if (lid) {
ZOLTAN_SET_ID(dd->lid_length, ptr->gid + dd->gid_length,
lid + i * dd->lid_length);
}
else {
memset(ptr->gid + dd->gid_length, 0, dd->lid_length);
}
if (user) {
memcpy(ptr->gid + (dd->gid_length + dd->lid_length),
user + (size_t)i * (size_t)(dd->user_data_length),
dd->user_data_length);
}
else {
memset(ptr->gid + (dd->gid_length + dd->lid_length), 0,
dd->user_data_length);
}
}
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After fill contact list");
/* now create efficient communication plan */
err = Zoltan_Comm_Create (&plan, count, procs, dd->comm,
ZOLTAN_DD_UPDATE_MSG_TAG, &nrec);
if (err != ZOLTAN_OK) {
ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Comm_Create error");
goto fini;
}
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Comm_Create");
/* If dd has no nodes allocated (e.g., first call to DD_Update;
* create the nodelist and freelist
*/
if (nrec && dd->nodelistlen == 0) {
DD_Memory_Alloc_Nodelist(dd, (DD_NodeIdx) nrec, 0.);
/* TODO Add overalloc parameter */
}
/* allocate receive buffer for nrec DD_Update_Msg structures */
if (nrec) {
rbuff = (char*)ZOLTAN_MALLOC((size_t)nrec*(size_t)(dd->update_msg_size));
if (rbuff == NULL) {
ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Receive buffer malloc failed");
err = ZOLTAN_MEMERR;
goto fini;
}
}
/* send my update messages & receive updates directed to me */
err = Zoltan_Comm_Do (plan, ZOLTAN_DD_UPDATE_MSG_TAG+1, sbuff,
dd->update_msg_size, rbuff);
if (err != ZOLTAN_OK) {
ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Comm_Do error");
goto fini;
}
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Comm_Do");
/* for each message rec'd, update local directory information */
errcount = 0;
rbufftmp = rbuff;
for (i = 0; i < nrec; i++) {
ptr = (DD_Update_Msg *) rbufftmp;
rbufftmp += dd->update_msg_size;
err = DD_Update_Local (dd, ptr->gid,
(ptr->lid_flag) ? (ptr->gid + dd->gid_length) : NULL,
(char*)((ptr->user_flag)?(ptr->gid+(dd->gid_length+dd->lid_length)):NULL),
(ptr->partition_flag) ? (ptr->partition) : -1, /* illegal partition */
ptr->owner);
if (err != ZOLTAN_OK)
++errcount;
}
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Local update");
err = ZOLTAN_OK;
if (dd->debug_level) /* overwrite error return if extra checking is on */
err = (errcount) ? ZOLTAN_WARN : ZOLTAN_OK;
fini:
ZOLTAN_FREE (&procs);
ZOLTAN_FREE (&sbuff);
ZOLTAN_FREE (&rbuff);
Zoltan_Comm_Destroy (&plan);
if (dd->debug_level) {
sprintf (str, "Processed %d GIDs (%d local), %d GID errors", count,
nrec, errcount);
ZOLTAN_PRINT_INFO (dd->my_proc, yo, str);
}
if (dd->debug_level > 4)
ZOLTAN_TRACE_OUT(dd->my_proc, yo, NULL);
return err;
}
/***************** DD_Update_Local () **********************/
/* DD_Update_Local() unconditionally updates the information associated
* with a global ID. If the gid was not found, it is added to the directory.
*/
static int DD_Update_Local (Zoltan_DD_Directory *dd,
ZOLTAN_ID_PTR gid, /* GID to update (in) */
ZOLTAN_ID_PTR lid, /* gid's LID (in), NULL if not needed */
char *user, /* gid's user data (in), NULL if not needed */
int partition, /* gid's partition (in), -1 if not used */
int owner) /* gid's current owner (proc number) (in) */
{
int index;
char *yo = "DD_Update_Local";
DD_NodeIdx nodeidx;
DD_Node *ptr;
/* input sanity checking */
if (dd == NULL || owner < 0 || owner >= dd->nproc || gid == NULL) {
ZOLTAN_PRINT_ERROR (dd ? dd->my_proc : ZOLTAN_DD_NO_PROC, yo,
"Invalid input parameter");
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 linked list until end looking for matching gid */
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) {
/* found match, update directory information */
if (lid)
ZOLTAN_SET_ID (dd->lid_length,ptr->gid + dd->gid_length, lid);
if (user)
memcpy(ptr->gid + (dd->gid_length + dd->lid_length), user,
dd->user_data_length);
ptr->owner = owner;
if (partition != -1)
ptr->partition = partition;
/* Response to multiple updates to a gid in 1 update cycle */
if (dd->debug_level > 0 && ptr->errcheck != owner) {
ZOLTAN_PRINT_INFO (dd->my_proc, yo, "Multiply defined GID");
if (dd->debug_level > 4)
ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL);
return ZOLTAN_WARN;
}
ptr->errcheck = owner;
if (dd->debug_level > 5)
ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL);
return ZOLTAN_OK; /* ignore all errors */
}
}
/* gid not found. Create new DD_Node and fill it in */
nodeidx = DD_Memory_Alloc_Node(dd);
ptr = dd->nodelist + nodeidx;
ZOLTAN_SET_ID (dd->gid_length, ptr->gid, gid);
if (lid) {
ZOLTAN_SET_ID(dd->lid_length,ptr->gid + dd->gid_length, lid);
}
else {
memset(ptr->gid + dd->gid_length, 0,
dd->lid_length*sizeof(ZOLTAN_ID_TYPE));
}
if (user) {
memcpy(ptr->gid + (dd->gid_length + dd->lid_length), user,
dd->user_data_length);
}
else {
memset(ptr->gid + (dd->gid_length+dd->lid_length), 0,
dd->user_data_length);
}
ptr->partition = partition;
ptr->owner = owner;
ptr->errcheck = owner;
/* Add node to the linked list */
ptr->next = dd->table[index];
dd->table[index] = nodeidx;
if (dd->debug_level > 6)
ZOLTAN_PRINT_INFO (dd->my_proc, yo, "Created new directory item");
if (dd->debug_level > 5)
ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL);
return ZOLTAN_OK;
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,458 @@
# @HEADER
#
########################################################################
#
# Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
# Copyright 2012 Sandia Corporation
#
# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
# the U.S. Government retains certain rights in this software.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the Corporation nor the names of the
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Questions? Contact Karen Devine kddevin@sandia.gov
# Erik Boman egboman@sandia.gov
#
########################################################################
#
# @HEADER
ZOLTAN Distributed Directory (DD) Software Documentation
The owner (i.e. the processor number) of any computational object is
subject to change during computation as a result of load balancing.
An application may use this directory module to find objects when it
needs them. A distributed directory balances the load (in terms of
memory and processing time) and avoids the bottle neck of a centralized
directory design.
This distributed directory module may be used alone or in conjunction
with Zoltan's load balancing capability and memory and communication
services. The user should note that external names (subroutines, etc.)
which prefaced by Zoltan_DD_ are reserved when using this module.
The user initially creates an empty distributed directory using
Zoltan_DD_Create. Then GID information is added to the directory using
Zoltan_DD_Update. Zoltan_DD_Update is also called after data migration
or refinements. The directory maintains the global ID's basic
information: local ID (optional), partition (optional), arbitrary user
data (optional), and current data owner. Zoltan_DD_Find returns this
information for a list of global IDs. When the user has finished using
the directory, its memory is returned to the system by Zoltan_DD_Destroy.
When necessary, a selected list of global IDs may be removed from the
directory by Zoltan_DD_Remove.
An object is known by its global ID. Hashing provides very fast
lookup for the information associated with a global ID in a two step
process. The first hash of the global ID yields the processor number
owning the directory entry for that global ID. The directory entry
owner remains constant even if the object (global ID) migrates in time.
Second, a different hash algorithm of the global ID looks up the
associated information in directory processor's hash table. The user
may optionally register their own (first) hash function to take
advantage of their knowledge of their global ID naming scheme and the
global ID's neighboring processors. See the documentation for
Zoltan_DD_Hash() for more information. If no user hash function is
registered, Zoltan's LB_Hash() will be used for the first hash. This
module's design was strongly influenced by the paper "Communication
Support for Adaptive Computation" by Pinar and Hendrickson.
The files DD_Set_Neighbor_Hash_Fn1 and DD_Set_Neighbor_Hash_Fn1 provide
examples of how a user can create their own hash functions taking advantage
of their knowledge of how the GID naming scheme might correlate to a
reasonable location for its directory information. These are also fully
tested and useful functions.
-----------------------------------
-----------------------------------
Source code location: Utilities/Directory
Function prototype file: Utilities/Directory/DD_Const.h
Library name: libzoltan_dd.a
Other libraries used by this library:
libmpi.a
libzoltan_mem.a
libzoltan_comm.a
Other header files used by this library
mem_const.h
comm_const.h
zoltan_util.h
Data Stuctures:
Zoltan_DD_Directory: state & storage used by all DD routines.
Routines:
Zoltan_DD_Create: Allocates memory and initializes the directory.
Zoltan_DD_Destroy: Terminate the directory and frees its memory.
Zoltan_DD_Update: Adds or updates global IDs' directory information.
Zoltan_DD_Find: Returns global IDs' information (owner, local ID, etc.)
Zoltan_DD_Remove: Eliminates selected global IDs from the directory.
Zoltan_DD_Stats: Provides statistics about hash table & linked lists.
Zoltan_DD_Print: Displays the contents (GIDs, etc) of each directory.
Zoltan_DD_Set_Hash_Fn: Registers a user's optional hash function.
Zoltan_DD_Set_Hash_Fn1: Model for user's to create their own hash function.
Zoltan_DD_Set_Hash_Fn2: Model for user's to create their own hash function.
Internal Data Structures: (not user accessable)
DD_Node: linked list element storing information about a global ID
DD_Update_Msg: Message with new data about global IDs
DD_Find_Msg: Messages to/from directory returning global IDs' info
DD_Remove_Msg: Message to eliminate all traces of selected global IDs.
Internal Routines: (not user callable)
DD_Update_Local:
DD_Find_local:
DD_Remove_Local:
DD_Hash2: // renamed copy of LB_Hash
Files in DDirectory:
DD_Const.h // return error codes, prototypes, structures
DD_Create.c
DD_Destroy.c
DD_Find.c
DD_Hash2.c
DD_Remove.c
DD_Set_Hash_Fn.c
DD_Set_Neighbor_Hash_Fn.c
DD_Stats.c
DD_Update.c
DD_Set_Hash_Fn1.c
DD_Set_Hash_Fn2.c
README // this file
---------------------------------------
---------------------------------------
int Zoltan_DD_Create (Zoltan_DD_Directory **dd, MPI_Comm comm,
int num_gid, int num_lid, int user_length, int table_length,
int debug_level)
----------------------------------------
Zoltan_DD_Create() allocates and initializes memory for the DD_Directory
structure. It must be called before any other distributed directory
routines. MPI must be initialized prior to calling Zoltan_DD_Create().
The DD_Directory struct must be passed to all other distributed directory
routines. The MPI Comm argument designates the processors used for the
distributed directory. The MPI Comm argument is duplicated and stored for
later use.
Note the need for double indirection in the DD_Directory calling argument
in order to allocate memory in behalf of the user program.
The user can set the debug level argument in the Zoltan_DD_Create()
to determine the module's response to multiple updates for any global ID
within one update cycle. If the argument is set to 0, all multiple updates
are ignored (but the last determines the directory information.) If the
argument is set to 1, an error is returned if the multiple updates
represent different owners for the same global ID. If the debug level is 2,
an error return and an error message are generated if multiple updates
represent different owners for the same global ID. If the level is 3, an
error return and an error message are generated for a multiple update even
if the updates represent the same owner for a global ID.
Arguments: (all are in)
dd Structure maintains directory state and hash table. (in/out)
comm MPI comm dup'ed & stored specifying directory processors.
num_gid Length of global ID.
num_lid Length of local ID or zero to ignore local IDs.
user_length Length of user defined data field (optional, may be zero).
table_length Length of hash table (zero forces default value).
debug_level Legal values range in [0,3]. Sets response to various error
conditions where 3 is the most verbose.
Return Value:
int Error code.
----------------------------------
----------------------------------
void Zoltan_DD_Destroy (Zoltan_DD_Directory **dd)
----------------------------------
This routine frees all memory allocated for the distributed directory.
No calls to any distributed directory functions are permitted after
calling this routine. Free() has no error return. Hence this routine
has no practical error return. MPI is necessary for this routine only
to free the previously saved MPI comm.
Arguments:
dd Directory structure to be deallocated
Returned Value:
NONE
-----------------------------------
-----------------------------------
int Zoltan_DD_Update (Zoltan_DD_Directory *dd, LB_ID_PTR gid,
LB_ID_PTR lid, LB_ID_PTR user, int *partition, int count)
-----------------------------------
Zoltan_DD_Update() takes a list of global IDs and corresponding lists of
optional local IDs, optional user data, and optional partitions. This
routine updates the information for existing directory entries or creates
a new entry (filled with given data) if a global ID is not found. NULL
lists should be passed for optional arguments not desired. If all
entries were found (and updated), the return is ZOLTAN_DD_NORMAL_RETURN.
If at least one global ID was not found, the return value is
ZOLTAN_DD_GID_ADDED. This function should be called initially and
whenever objects are migrated to keep the distributed directory current.
The user can set the debug level argument in the Zoltan_DD_Create()
to determine the module's response to multiple updates for any global ID
within one update cycle. If the argument is set to 0, all multiple updates
are ignored (but the last determines the directory information.) If the
argument is set to 1, an error is returned if the multiple updates
represent different owners for the same global ID. If the debug level is 2,
an error return and an error message are generated if multiple updates
represent different owners for the same global ID. If the level is 3, an
error return and an error message are generated for a multiple update even
if the updates represent the same owner for a global ID.
Arguments:
dd Distributed directory structure state information.
gid List of global IDs to update (in).
lid List of corresponding local IDs (optional) (in).
user List of corresponding user data (optional) (in).
partition List of corresponding partitions (optional) (in).
count Number of global IDs in update list.
Returned Value:
int Error code.
------------------------------------
------------------------------------
int Zoltan_DD_Find (Zoltan_DD_DDirectory *dd, LB_ID_PTR gid,
LB_ID_PTR lid, LB_ID_PTR data, int *partition, int count,
int *owner)
------------------------------------
Given a list of global IDs, Zoltan_DD_Find() returns corresponding
lists of the global IDs' owners, local IDs, partitions, and optional
user data. NULL lists must be provided for optional information not
being used.
Arguments:
dd Distributed directory structure state information.
gid List of global IDs whose information is requested.
lid Corresponding list of local IDs (optional) (out).
data Corresponding list of user data (optional) (out).
partition Corresponding list of partitions (optional) (out).
count Count of global IDs in above list
owner Corresponding list of data owners (out).
Returned Value:
int Error code.
------------------------------------
------------------------------------
int Zoltan_DD_Remove (Zoltan_DD_Directory *dd, LB_ID_PTR gid,
int count)
------------------------------------
Zoltan_DD_Remove() takes a list of global_IDs and removes all of
their information from the distributed directory.
Arguments:
dd Distributed directory structure state information.
gid List of global IDs to eliminate from the directory.
count Number of global IDs to be removed.
Returned Value:
int Error code.
-------------------------------------
-------------------------------------
void Zoltan_DD_Set_Hash_Fn (Zoltan_DD_Directory *dd,
unsigned int (*hash) (LB_ID_PTR, int, unsigned int))
-------------------------------------
Enables the user to register a new hash function for the distributed
directory. (If this routine is not called, the default hash function
LB_Hash() will be used automatically.) This hash function determines
which processor maintains the distributed directory entry for a given
global ID. Inexperienced users do not need this routine.
Experienced users may elect to create their own hash function based on
their knowledge of their global ID naming scheme. The user's hash
function must have calling arguments compatible with LB_Hash().
Consider that a user has defined a hash function, myhash, as
unsigned int myhash(LB_ID_PTR gid, int length, unsigned int naverage)
{
return *gid / naverage ; // length assumed to be 1
// naverage = total_gids/nproc
}
Then the call to register this hash function is:
Zoltan_DD_Set_Hash (myhash) ;
NOTE: This hash function might group the gid's directory information
near the gid's owning processor's neighborhood, for an
appropriate naming scheme.
Arguments:
dd Distributed directory structure state information.
hash Name of user's hash function.
Returned Value:
NONE
----------------------------------------
----------------------------------------
void Zoltan_DD_Stats (Zoltan_DD_Directory *dd)
----------------------------------------
This routine prints out summary information about the local distributed
directory. It includes the hash table length, number of GIDs stored in
the local directory, the number of linked lists, and the length of the
longest linked list. The dd->debug_level (set by an argument into the
Zoltan_DD_Create function controls this routines verbosity.
Arguments:
dd Distributed directory structure for state information
Returned Value:
NONE
----------------------------------------
----------------------------------------
int Zoltan_DD_Set_Neighbor_Hash_Fn1 (Zoltan_DD_Directory *dd, int size)
----------------------------------------
This routine associates the first size GIDs to proc 0, the next size to
proc 1, etc. It assumes the GIDs are consecutive numbers. It assumes
that GIDs primarily stay near their original owner. The GID length is
assumed to be 1. GIDs outside of the range are evenly distributed among
the processors via modulo(nproc). This is a model for the user to develop
their own similar routine.
Arguments: (all are in)
dd Structure maintains directory state and hash table.
size Number of consecutive GIDs associated with a processor.
Return Value:
int Error Code.
----------------------------------------
----------------------------------------
int Zoltan_DD_Set_Neighbor_Hash_Fn2 (Zoltan_DD_Directory *dd, int *proc,
int *low, int *high, int n)
----------------------------------------
This routine allows the user to specify a beginning and ending GID
"numbers" per directory processor. It assumes that GIDs primarily stay
near their original owner. It requires that the numbers of high, low, &
proc entries are all n. It assumes the GID length is 1. It is a model for
the user to develop their own similar routine. Users should note the
registration of a cleanup routine to free local static memory when the
distributed directory is destroyed. GIDs outside the range specified by
high and low lists are evenly distributed among the processors via modulo
(nproc).
Arguments: (all are in)
dd Structure maintains directory state and hash table.
proc List of processor ids labeling for corresponding high, low value.
low List of low GID limits corresponding to proc list.
high List of high GID limits corresponding to proc list.
n Number of elements in the above lists. Should be nproc!
Return Value:
int Error Code.
----------------------------------------
----------------------------------------
int Zoltan_DD_Print (Zoltan_DD_Directory *dd)
----------------------------------------
This utility displays (to stdout) the entire contents of the distributed
directory at one line per GID.
Arguments:
dd Structure maintains directory state and hash table.
Return Value:
int Error Code.
----------------------------------------
/***************** Developer's Notes *****************************/
Because Zoltan places no restrictions on the content or length of global
IDs, hashing does not guarantee a balanced distribution of objects in
the distributed directory. Note also, the worst case behavior of a hash
table lookup is very bad (essentially becoming a linear search).
Fortunately, the average behavior is very good! The user may specify
their own hash function in place of the default LB_Hash() to improve
performance.
This software module is built on top of the Zoltan Communications
functions for efficiency. Improvements to the communications library
will automatically benefit the distributed directory.
Global BUG: The distributed directory should be implemented via
client-server processes or threads. However, MPI is
not fully thread aware, yet.
FUTURE: The C99 capability for variable length arrays would
significantly simplify many of these following
routines. (It eliminates the malloc/free calls for
temporary storage. This helps prevent memory leaks.)
Other C99 features may also improve code readability.
The "inline" capability can potentially improve
performance.

View File

@ -0,0 +1,204 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef ZOLTAN_DD_H
#define ZOLTAN_DD_H
#include "zoltan_mem.h"
#include "zoltan_comm.h"
#include "zoltan_types.h"
#include "zoltan_id.h"
#include "zoltan_util.h"
#include "zoltan_dd.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#define ZOLTAN_DD_HASH_TABLE_COUNT 100000 /* default # of linked list heads */
#define ZOLTAN_DD_NO_PROC -1 /* not a possible processor # */
/* Tags for MPI communications. These need unique values. Arbitrary */
#define ZOLTAN_DD_FIND_MSG_TAG 29137 /* needs 3 consecutive values */
#define ZOLTAN_DD_UPDATE_MSG_TAG 29140 /* needs 2 consecutive values */
#define ZOLTAN_DD_REMOVE_MSG_TAG 29142 /* needs 2 consecutive values */
#ifndef TRUE
#define FALSE (0)
#define TRUE (1)
#endif /* !TRUE */
/*********** Distributed Directory Function Prototypes ************/
unsigned int Zoltan_DD_Hash2(ZOLTAN_ID_PTR key, int num_id_entries,
unsigned int n, void *hashdata, ZOLTAN_HASH_FN *fn);
void Zoltan_DD_default_cleanup(void *hashdata);
typedef unsigned int DD_Hash_fn(ZOLTAN_ID_PTR, int, unsigned int, void *,
ZOLTAN_HASH_FN *);
typedef void DD_Cleanup_fn(void*);
/************ Zoltan_DD_Directory, DD_Node **********************/
typedef int DD_NodeIdx; /* Index into dd->nodelist;
must be a signed type as -1 indicates NULL */
/* The following structure, DD_Node, is the basic unit of the hash table's
* linked list. DD_Node contains the global ID(used as the table lookup
* key) and other necessary information. NOTE: DD_Node is malloc'd to
* store gid, lid & user data beyond the struct's end.
*/
typedef struct DD_Node {
int owner; /* processor hosting global ID object */
int partition; /* Optional data */
int errcheck; /* Error checking(inconsistent updates) */
DD_NodeIdx next; /* index in nodelist of next DD_Node in
linked list or free node list */
ZOLTAN_ID_TYPE *gid; /* gid used as key for update & lookup */
/* lid starts at gid + dd->gid_length */
/*(user) data starts at */
/* gid + dd->gid_length + dd->lid_length */
int free; /* flag indicating whether node is
free or used */
} DD_Node;
/* The directory structure, Zoltan_DD_Struct, is created by the call
* to Zoltan_DD_Create(). It maintains the state information and storage
* allocation for the distributed directory. Other state information may
* be added in the future. This structure must be passed back to all other
* distributed directory calls: Zoltan_DD_Update(), Zoltan_DD_Find(),
* Zoltan_DD_Destroy(), Zoltan_DD_Set_Hash_Fn(), DD_Update_Local(),
* DD_Find_Local(), DD_Remove_Local(). NOTE: Zoltan_DD_Struct is
* malloc'd for storage beyond the struct's end to hold hash table.
*/
struct Zoltan_DD_Struct {
int my_proc; /* My identity in MPI Comm */
int nproc; /* Number of processors in MPI Comm */
int gid_length; /* = zz->Num_GID -- avoid needing Zoltan_Struct */
int lid_length; /* = zz->Num_LID -- avoid needing Zoltan_Struct */
int max_id_length; /* max(gid_length, lid_length) */
int user_data_length; /* Optional user data length in chars */
int table_length; /* # of heads of linked lists */
size_t nodedata_size; /* Malloc for GID & LID & user storage */
size_t find_msg_size; /* Total allocation for DD_FIND_MSG */
size_t update_msg_size; /* Total allocation for DD_UPDATE_MSG */
size_t remove_msg_size; /* Total allocation for DD_REMOVE_MSG */
int debug_level; /* Determines actions to multiple updates */
DD_Hash_fn *hash; /* Hash function used by this DD */
void *hashdata; /* Either our hash data ... */
ZOLTAN_HASH_FN *hashfn; /* ... Or user's hash function, not both */
DD_Cleanup_fn *cleanup; /* Functioned to free our hash data */
MPI_Comm comm; /* Dup of original MPI Comm(KDD) */
DD_NodeIdx nodecnt; /* Number of nodes used in nodelist */
/* AKA Number of local entries in directory */
DD_Node *nodelist; /* Memory for storing all nodes in the directory */
char *nodedata; /* Memory for storing all data in the directory */
DD_NodeIdx nodelistlen; /* Length of the nodelist. */
DD_NodeIdx nextfreenode;/* Index of first free node in nodelist;
-1 if no nodes are free */
DD_NodeIdx table[1]; /* Hash table heads of the link lists */
};
/*************** DD Communication Messages *********************/
/* Note: These message structures should become MPI datatypes(KDD) */
typedef struct { /* Only used by Zoltan_DD_Update() */
char lid_flag; /* indicates if LID data are present */
char user_flag; /* indicates if USER data are present */
char partition_flag; /* indicates if optional partition data present */
int owner; /* range [0, nproc-1] or -1 */
int partition;
ZOLTAN_ID_TYPE gid[1]; /* struct malloc'd to include gid & lid & user */
/* LID found at gid[dd->gid_length] */
/* USER found at gid[dd->gid_length */
/* + dd->lid_length] if used */
} DD_Update_Msg;
/* A single structure can serve for both the request and its answer(in
* DD_Find_Msg if its memory is sized to hold either a global ID or a
* local ID. On the request direction, the proc field is the
* destination and the id field holds the global ID being located. In
* the return direction, the proc field holds the objects location and
* the id field holds its corresponding local ID. The index field is
* untouched & unused.
*/
typedef struct { /* Only used by Zoltan_DD_Find() */
int proc; /* destination or location */
int partition;
int index; /* to put things back in order afterward */
ZOLTAN_ID_TYPE id[1]; /* allocated as max(Num_GID, Num_LID) */
/* + user data length */
} DD_Find_Msg;
typedef struct { /* Only used by Zoltan_DD_Remove() */
int owner; /* range [0, nproc-1] or -1 */
ZOLTAN_ID_TYPE gid[1]; /* structure malloc'd to include gid */
} DD_Remove_Msg;
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif
#endif

View File

@ -0,0 +1,62 @@
# @HEADER
#
########################################################################
#
# Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
# Copyright 2012 Sandia Corporation
#
# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
# the U.S. Government retains certain rights in this software.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the Corporation nor the names of the
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Questions? Contact Karen Devine kddevin@sandia.gov
# Erik Boman egboman@sandia.gov
#
########################################################################
#
# @HEADER
MEMORY UTILITIES -- Routines for memory allocation and deallocation.
----------------------------------------------------------------
Files compiled into Zoltan:
zoltan_mem.h -- Prototypes for memory allocation and deallocation
routines in mem.c. Definition of Zoltan_MALLOC.
mem.c -- Memory allocation routines Zoltan_Array_Alloc and
Zoltan_Malloc.
Memory deallocation routine Zoltan_Free.
Parameter setting routing Zoltan_Set_Malloc_Param.
----------------------------------------------------------------
Memory test program
mem_main.c -- Stub for a driver program.

View File

@ -0,0 +1,682 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zoltan_mem.h"
#include "zoltan_util.h"
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
static int DEBUG_MEMORY = 0; /* Flag for detecting memory leaks */
static size_t bytes_used = 0; /* Sum of active allocations */
static size_t bytes_max = 0; /* Largest total of active allocations */
#ifdef REALLOC_BUG
static size_t max_alloc = 0; /* Largest single allocation */
#endif
static int nmalloc = 0; /* number of calls to malloc */
static int nfree = 0; /* number of calls to free */
/* Macro to get rank information for printing and error messages. */
/* If not using MPI, compile with -DZOLTAN_NO_MPI; all messages */
/* will print with proc = 0. */
#ifdef ZOLTAN_NO_MPI
#define GET_RANK(a) *(a)=0
#else
#include <mpi.h>
#define GET_RANK(a) MPI_Comm_rank(MPI_COMM_WORLD, (a))
#endif
#define MAX_STRING_LEN 50
static struct malloc_debug_data {
int order; /* which malloc call is it? */
size_t size; /* size of malloc invocation */
double *ptr; /* memory location returned */
char file[MAX_STRING_LEN+1]; /* file name */
int line; /* line number */
struct malloc_debug_data *next; /* pointer to next element */
} *top = NULL;
/******************************************************************************/
void Zoltan_Memory_Debug(int new_level) {
/*
* Routine to allow user to set DEBUG_MEMORY level.
*/
DEBUG_MEMORY = new_level;
}
/******************************************************************************/
int Zoltan_Memory_Get_Debug() {
return DEBUG_MEMORY;
}
/******************************************************************************
*
* Dynamic Allocation of Multidimensional Arrays
*-----------------------------------------------------------------------------
*
* Example Usage:
*
* typedef struct
* { int bus1;
* int bus2;
* int dest;
* } POINT;
*
* POINT **points, corner;
*
* points = (POINT **)Zoltan_Array_Alloc(file,lineno,2,x,y,sizeof(POINT));
* ^ ^ ^ ^ ^
* | | | | |
* name of calling file--------* | | | |
* | | | |
* line number of call--------------* | | |
* | | |
* number of dimensions-------------------+ | |
* | |
* first dimension max---------------------+ |
* |
* second dimension max-----------------------+
*
* (points may be now be used as if it were declared
* POINT points[x][y])
*
* This particular version is limited to dimensions of 4 or less.
*
* corner = points[2][3]; (refer to the structure as you would any array)
*
* free (points); (frees the entire structure in one fell swoop)
*
*****************************************************************************/
/******************************************************************************
* The following section is a commented section containing
* an example main code:
*******************************************************************************
*double *Zoltan_Array_Alloc();
*main()
*{
* int ***temp;
* int *temp2;
* int i, j, k;
* int il, jl, kl;
*
* malloc_debug(2);
* il = 2;
* jl = 3;
* kl = 3;
* temp = (int ***) Array_Alloc(__FILE__,__LINE__,3,il,jl,kl,sizeof(int));
* for (i=0; i<il; i++) {
* for (j=0; j<jl; j++) {
* for (k=0; k<kl; k++) temp[i][j][k] = 1;
* }
* }
*
* temp2 = (int *) malloc(10*sizeof(int));
* for (i=0; i<10; i++) temp2[i] = 0;
*
* for (i=0; i<il; i++) {
* for (j=0; j<jl; j++) {
* for (k=0; k<kl; k++) (void) printf(" %d\n", temp[i][j][k]);
* }
* }
* malloc_verify();
*}
******************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
#ifdef __STDC__
double *Zoltan_Array_Alloc(char *file, int lineno, int numdim, ...)
#else
double *Zoltan_Array_Alloc(va_alist)
va_dcl
#endif
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
{
char *yo = "Zoltan_Array_Alloc";
int i, j;
struct dimension {
long index; /* Number of elements in the dimension */
long total; /* Total number of elements */
long size; /* Size of a single element in bytes */
long off; /* offset from beginning of array */
} dim[4]; /* Info about each dimension */
#ifndef __STDC__
char *file; /* Filename of source code from call. */
int lineno; /* Line number of call. */
int numdim; /* Number of dimensions */
#endif
long total; /* Total size of the array */
double *dfield; /* ptr to avoid lint complaints */
char *field; /* The multi-dimensional array */
char **ptr; /* Pointer offset */
char *data; /* Data offset */
va_list va; /* Current pointer in the argument list */
#ifdef __STDC__
va_start(va, numdim);
#else
va_start(va);
file = va_arg(va, char *);
lineno = va_arg(va, int);
numdim = va_arg(va, int);
#endif
if (numdim <= 0) {
fprintf(stderr, "%s (%s: %d) ERROR: number of dimensions, %d, is <=0\n",
yo, file, lineno, numdim);
va_end(va);
return((double *) NULL);
}
else if (numdim > 4) {
fprintf(stderr, "%s (%s: %d) ERROR: number of dimensions, %d, is > 4\n",
yo, file, lineno, numdim);
va_end(va);
return((double *) NULL);
}
dim[0].index = va_arg(va, int);
if (dim[0].index <= 0) {
if (DEBUG_MEMORY > 0) {
fprintf(stderr, "WARNING, %s (%s: %d) called with first "
"dimension <= 0, %ld; will return NULL\n",
yo, file, lineno, dim[0].index);
}
va_end(va);
return((double *) NULL);
}
dim[0].total = dim[0].index;
dim[0].size = sizeof(void *);
dim[0].off = 0;
for (i = 1; i < numdim; i++) {
dim[i].index = va_arg(va, int);
if (dim[i].index <= 0) {
fprintf(stderr, "WARNING: %s (%s: %d) called with dimension %d <= 0, "
"%ld; will return NULL\n",
yo, file, lineno, i+1, dim[i].index);
va_end(va);
return((double *) NULL);
}
dim[i].total = dim[i-1].total * dim[i].index;
dim[i].size = sizeof(void *);
dim[i].off = dim[i-1].off + dim[i-1].total * dim[i-1].size;
}
dim[numdim-1].size = va_arg(va, int);
va_end(va);
/* Round up the last offset value so data is properly aligned. */
dim[numdim-1].off = dim[numdim-1].size *
((dim[numdim-1].off+dim[numdim-1].size-1)/dim[numdim-1].size);
total = dim[numdim-1].off + dim[numdim-1].total * dim[numdim-1].size;
dfield = (double *) Zoltan_Malloc(total, file, lineno);
if (dfield != NULL) {
field = (char *) dfield;
for (i = 0; i < numdim - 1; i++) {
ptr = (char **) (field + dim[i].off);
data = (char *) (field + dim[i+1].off);
for (j = 0; j < dim[i].total; j++) {
ptr[j] = data + j * dim[i+1].size * dim[i+1].index;
}
}
}
return dfield;
} /* Zoltan_Array_Alloc */
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
/* Safe version of calloc. */
double *Zoltan_Calloc (size_t num, size_t size, char *filename, int lineno)
{
double *p ;
p = Zoltan_Malloc (num*size, filename, lineno) ;
if (p) memset ((void *) p, '\0', num*size) ;
return p ;
}
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
/* Safe version of malloc. Does not initialize memory .*/
double *Zoltan_Malloc(size_t n, char *filename, int lineno)
{
char *yo = "Zoltan_Malloc";
struct malloc_debug_data *new_ptr; /* data structure for malloc data */
int proc; /* processor ID for debugging msg */
double *pntr; /* return value */
char *basefile;
if (n > 0) {
#ifdef REALLOC_BUG
if (n > max_alloc){
max_alloc = n;
}
n += sizeof(double);
#endif
pntr = (double *) malloc(n);
if (pntr == NULL) {
GET_RANK(&proc);
fprintf(stderr, "%s (from %s,%d) No space on proc %d - number of bytes "
"requested = %lu\n", yo, filename, lineno, proc,
(unsigned long) n);
return ((double *) NULL);
}
nmalloc++;
#ifdef REALLOC_BUG
pntr[0] = (double)(n - sizeof(double));
++pntr;
#endif
}
else if (n == 0)
pntr = NULL;
else { /* n < 0 */
GET_RANK(&proc);
fprintf(stderr, "%s (from %s,%d) ERROR on proc %d: "
"Negative malloc argument. (%lu)\n", yo, filename, lineno, proc,
(unsigned long) n);
return ((double *) NULL);
}
if (DEBUG_MEMORY > 1 && pntr != NULL) {
/* Add allocation to linked list of active allocations. */
new_ptr = (struct malloc_debug_data *)
malloc(sizeof(struct malloc_debug_data));
if (new_ptr == NULL) {
GET_RANK(&proc);
fprintf(stderr, "WARNING: No space on proc %d for malloc_debug %lu.\n",
proc, (unsigned long) n);
return (pntr);
}
new_ptr->order = nmalloc;
new_ptr->size = n;
new_ptr->ptr = pntr;
#ifdef SHORT_FILE
basefile = strrchr(filename, '/');
basefile = ((basefile != NULL)?basefile:filename-1)+1;
#else
basefile = filename;
#endif /* SHORT_FILE */
strncpy(new_ptr->file, basefile, MAX_STRING_LEN);
new_ptr->line = lineno;
new_ptr->next = top;
top = new_ptr;
bytes_used += n;
if (bytes_used > bytes_max) {
bytes_max = bytes_used;
}
}
if (DEBUG_MEMORY > 2) {
/* Print out details of allocation. */
GET_RANK(&proc);
fprintf(stderr, "Proc %d: order=%d, size=%lu, location=0x%lx, "
"file=%s, line=%d\n",
proc, nmalloc, (unsigned long) n, (long) pntr, filename, lineno);
}
return pntr;
} /* Zoltan_Malloc */
/* Safe version of realloc. Does not initialize memory. */
double *Zoltan_Realloc(void *ptr, size_t n, char *filename, int lineno)
{
char *yo = "Zoltan_Realloc";
struct malloc_debug_data *dbptr; /* loops through debug list */
int proc; /* processor ID */
double *p; /* returned pointer */
#ifdef REALLOC_BUG
int n_old;
#endif
if (ptr == NULL) { /* Previous allocation not important */
if (n == 0) {
p = NULL;
}
else {
p = Zoltan_Malloc(n, filename, lineno);
}
}
else {
if (n == 0) {
Zoltan_Free((void **) &ptr, filename, lineno);
p = NULL;
}
else {
#ifdef REALLOC_BUG
/* Feb 10, 2010: Several platforms show a realloc bug where realloc
* either fails to allocate memory when there is sufficient memory
* or it crashes. If realloc shows this failure, then build Zoltan
* with REALLOC_BUG, and we will call malloc/memcpy/free instead.
*/
p = (double *)ptr;
p--;
n_old = p[0];
if ((n_old < 1) || (n_old > max_alloc)){ /* sanity check */
GET_RANK(&proc);
fprintf(stderr, "%s (from %s,%d) Zoltan_Realloc called on a pointer "
"that was not returned by Zoltan_Malloc (proc %d)\n",
yo, filename, lineno, proc);
return NULL;
}
p = (double *) Zoltan_Malloc(n, filename, lineno);
if (p){
if (n > n_old){
memcpy(p, ptr, n_old);
}
else if (n <= n_old){
memcpy(p, ptr, n);
}
Zoltan_Free((void **) &ptr, filename, lineno);
}
#else
p = (double *) realloc((char *) ptr, n);
if (DEBUG_MEMORY > 1) {
/* Need to replace item in allocation list */
for (dbptr = top; dbptr != NULL && (void *) (dbptr->ptr) != ptr;
dbptr = dbptr->next);
if (dbptr == NULL) { /* previous allocation not found in list. */
GET_RANK(&proc);
fprintf(stderr, "Proc %d: Memory error: "
"In realloc, address not found in debug list (0x%lx)\n",
proc, (long) ptr);
}
else { /* Update entry in allocation list */
bytes_used += (n - dbptr->size);
dbptr->size = n;
dbptr->ptr = p;
if (bytes_used > bytes_max) {
bytes_max = bytes_used;
}
}
}
if (p == NULL) {
GET_RANK(&proc);
fprintf(stderr, "%s (from %s,%d) No space on proc %d - "
"number of bytes requested = %lu\n",
yo, filename, lineno, proc, (unsigned long) n);
}
#endif
}
}
return (p);
} /* Zoltan_Realloc */
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
void Zoltan_Free (void **ptr, char *filename, int lineno)
{
struct malloc_debug_data *dbptr; /* loops through debug list */
struct malloc_debug_data **prev; /* holds previous pointer */
int proc; /* processor ID */
#ifdef REALLOC_BUG
double *p=NULL;
#endif
/*
* This version of free calls the system's free function. It doesn't call
* free if ptr is the NULL pointer.
*/
if (ptr == NULL || *ptr == NULL)
return;
nfree++;
if (DEBUG_MEMORY > 1) {
/* Remove allocation of list of active allocations */
prev = &top;
for (dbptr = top; dbptr != NULL && (void *) (dbptr->ptr) != *ptr;
dbptr = dbptr->next) {
prev = &(dbptr->next);
}
if (dbptr == NULL) {
GET_RANK(&proc);
fprintf(stderr, "Proc %d: Memory error: In free, address (0x%lx) "
"not found in debug list. File=%s, line=%d.\n", proc,
(long) *ptr, filename, lineno);
}
else {
*prev = dbptr->next;
bytes_used -= dbptr->size;
free((char *) dbptr);
if (DEBUG_MEMORY > 2){
GET_RANK(&proc);
fprintf(stderr, "Proc %d: free, address (0x%lx) "
"File=%s, line=%d.\n", proc, (long) *ptr, filename, lineno);
}
}
}
#ifdef REALLOC_BUG
p = (double *)*ptr;
free(p-1);
#else
free(*ptr);
#endif
/* Set value of ptr to NULL, to flag further references to it. */
*ptr = NULL;
} /* Zoltan_Free */
/* Free n pointers. Variable number of arguments is allowed. */
#ifdef __STDC__
void Zoltan_Multifree(char *filename, int lineno, int n, ...)
{
int i;
va_list va;
va_start(va, n);
for (i=0; i<n; i++){
Zoltan_Free(va_arg(va, void **), filename, lineno);
}
va_end(va);
}
#else
void Zoltan_Multifree(va_alist)
va_dcl
{
int i, n, lineno;
char *filename;
va_list va;
va_start(va);
filename = va_arg(va, char *);
lineno = va_arg(va, int);
n = va_arg(va, int);
for (i=0; i<n; i++){
Zoltan_Free(va_arg(va, void **), filename, lineno);
}
va_end(va);
}
#endif
/* Print out status of malloc/free calls. Flag any memory leaks. */
void Zoltan_Memory_Stats()
{
struct malloc_debug_data *dbptr; /* loops through debug list */
int proc; /* processor ID */
if (DEBUG_MEMORY == 1) {
GET_RANK(&proc);
fprintf(stderr, "Proc %d: Calls to malloc = %d, Calls to free = %d\n",
proc, nmalloc, nfree);
if (nmalloc > nfree)
fprintf(stderr, "Proc %d: Possible memory error: "
"# malloc > # free.\n", proc);
else if (nfree > nmalloc)
fprintf(stderr, "Proc %d: Possible memory error: "
"# free > # malloc.\n", proc);
}
else if (DEBUG_MEMORY > 1) {
GET_RANK(&proc);
fprintf(stderr, "Proc %d: Calls to malloc = %d, Calls to free = %d, "
"Max bytes = %lu, total bytes = %lu\n",
proc, nmalloc, nfree,
(unsigned long) bytes_max, (unsigned long) bytes_used);
if (nmalloc > nfree)
fprintf(stderr, "Proc %d: Possible memory error: "
"# malloc > # free.\n", proc);
else if (nfree > nmalloc)
fprintf(stderr, "Proc %d: Possible memory error: "
"# free > # malloc.\n", proc);
if (top != NULL) {
fprintf(stderr, "Proc %d: Remaining allocations:\n", proc);
for (dbptr = top; dbptr != NULL; dbptr = dbptr->next) {
fprintf(stderr, " order=%d, size=%lu, location=0x%lx, "
"file=%s, line=%d\n",
dbptr->order, (unsigned long) (dbptr->size),
(long) dbptr->ptr,
dbptr->file, dbptr->line);
}
}
}
} /* Zoltan_Memory_Stats */
int Zoltan_Malloc_Num(void)
{
/* Return number associated with the most recent malloc call. */
return (nmalloc);
} /* Zoltan_Malloc_Num */
size_t Zoltan_Memory_Usage (int type)
{
/* Return memory usage information: total bytes used currently or *
* maximum bytes used at any point. Default is maximum bytes used. */
if (type == ZOLTAN_MEM_STAT_TOTAL)
return bytes_used ;
return bytes_max ;
}
void Zoltan_Memory_Reset (int type)
{
/* Reset total bytes used currently or maximum bytes used at any point
to zero. */
if (type == ZOLTAN_MEM_STAT_TOTAL)
bytes_used = 0;
else
bytes_max = 0;
}
/*****************************************************************************/
/* END of mem.c */
/*****************************************************************************/
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

65
thirdParty/Zoltan/src/Utilities/README vendored Normal file
View File

@ -0,0 +1,65 @@
# @HEADER
#
########################################################################
#
# Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
# Copyright 2012 Sandia Corporation
#
# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
# the U.S. Government retains certain rights in this software.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the Corporation nor the names of the
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Questions? Contact Karen Devine kddevin@sandia.gov
# Erik Boman egboman@sandia.gov
#
########################################################################
#
# @HEADER
Zoltan Utilities
The following utilities are represented in this directory; details of
individual utilities can be found in README files in the appropriate
subdirectories. Each utility builds its own library.
Utility Subdirectory Library Name
----------------------------------------------------------------------------
Memory Management Memory libzoltan_mem.a
Unstructured Communication Communication libzoltan_comm.a
Distributed Directory DDirectory libzoltan_dd.a
A single Makefile builds all the utilities. For directions on building
utilities, type "gmake help" in this directorry.
Configuration files for compilation and linking on various architectures
are included in the directory Config. These configuration files are
shared by Zoltan and the utilities; thus, some fields in the configuration
files are not used by all utilities.

View File

@ -0,0 +1,53 @@
# @HEADER
#
########################################################################
#
# Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
# Copyright 2012 Sandia Corporation
#
# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
# the U.S. Government retains certain rights in this software.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the Corporation nor the names of the
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Questions? Contact Karen Devine kddevin@sandia.gov
# Erik Boman egboman@sandia.gov
#
########################################################################
#
# @HEADER
TIMER UTILITY -- Routines to implement Zoltan_Time and Zoltan_Timer objects.
----------------------------------------------------------------------------
Files compiled into libzoltan_timer.a and libzoltan.a:
timer.c -- Routines implementing Zoltan_Time.
timer.h -- Prototypes and constants.
zoltan_timer.c -- Implementation of timer object.
zoltan_timer.h -- Interface to timer object.

View File

@ -0,0 +1,144 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <mpi.h>
#include "timer.h"
#include "zoltan_util.h"
#ifdef __PUMAGON__
#include <nx.h>
#endif
/****************************************
* Machine independent timing utilities.
* ANSI C and MPI are required.
****************************************/
/* Timer routine that returns either CPU or wall-clock time.
The ANSI function clock() may roll over at approx 71.5 minutes,
on some systems so we try to determine the number of rollovers.
*/
double Zoltan_Time(int timer)
{
double t = -1.;
#if !defined(__PUMAGON__) && !defined(__LIBCATAMOUNT__)
clock_t num_ticks;
static clock_t last_num_ticks = 0;
static int clock_rollovers = 0;
static double secs_per_clock = (double) 1./((double) CLOCKS_PER_SEC);
static double clock_width =
((double)(1L<<((int)sizeof(clock_t)*8-2)))*4./((double) CLOCKS_PER_SEC);
static double secs_per_tick = 0.; /* Not necessarily the same as
secs_per_clock; system-dependent; get value from sysconf(). */
#endif
if (timer==ZOLTAN_TIME_WALL)
/* Wall clock */
t = MPI_Wtime();
else if (timer==ZOLTAN_TIME_CPU) {
#if defined(__PUMAGON__) || defined(__LIBCATAMOUNT__)
/* CPU time on ASCI Red and Red Storm. */
t = dclock();
#else
/* CPU time */
num_ticks = clock();
if (num_ticks < last_num_ticks) clock_rollovers++;
t = num_ticks * secs_per_clock;
if (clock_rollovers) t += clock_rollovers * clock_width;
last_num_ticks = num_ticks;
#endif
}
#ifndef NO_TIMES
else if (timer==ZOLTAN_TIME_USER) {
struct tms tm;
if (secs_per_tick == 0.)
secs_per_tick = (double) 1. / ((double) sysconf(_SC_CLK_TCK));
times(&tm);
t = tm.tms_utime * secs_per_tick;
}
#endif
return t;
}
/* Resolution (precision) of timer.
* This is really a lower bound, the actual resolution may be worse.
* If the precision is unknown, -1 is returned.
*/
double Zoltan_Time_Resolution(int timer)
{
double t = -1.;
if (timer==ZOLTAN_TIME_WALL)
t = MPI_Wtick();
else if (timer==ZOLTAN_TIME_CPU)
t = (double) 1. / ((double) CLOCKS_PER_SEC);
#ifndef NO_TIMES
else if (timer==ZOLTAN_TIME_USER)
t = (double) 1. / ((double) sysconf(_SC_CLK_TCK));
#endif
return t;
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,77 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef __TIMER_H
#define __TIMER_H
#include "zoltan_timer.h"
#include <time.h> /* ANSI C; defines clock_t and clock() */
#ifndef CLOCKS_PER_SEC /* Should have been defined in time.h */
#define CLOCKS_PER_SEC 1000000 /* To prevent compile errors, not always the correct value. */
#endif
/*
* POSIX compliant systems should use times() for user timing.
* This is the default in Zoltan. Make Zoltan with -DNO_TIMES if
* your system does not have sys/times.h and times().
* Note: BSD-like systems may use getrusage() instead for user timing,
* but that has not been implemented here.
*/
#if defined(__PUMAGON__) || defined(__LIBCATAMOUNT__) || defined(_WIN32)
/* Tflops with Cougar & Red Storm w/Catamount does not have sysconf() or times() */
/* Microsoft Visual Studio does not have times either */
#define NO_TIMES
#endif /* __PUMAGON__ */
#ifndef NO_TIMES
/* #include <sys/types.h> -- Included by sys/times.h on most systems. */
#include <sys/times.h>
#include <unistd.h> /* Needed for sysconf() and _SC_CLK_TCK */
#endif
#endif

View File

@ -0,0 +1,468 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include "zoltan_timer.h"
#include "zoltan_types.h"
#include "zoltan_util.h"
#include "zoltan_mem.h"
#ifdef VAMPIR
#include <VT.h>
#endif
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/****************************************************************************/
/*
* Functions that implement a Timer "class," creating a Timer object
* with start, stop and print functions.
*
* This code was designed to be a stand-alone utility, relying only
* on Zoltan_Time, Zoltan error codes, Zoltan utilities, and libzoltan_mem.a.
* Some rearranging of the Zoltan_Time files is necessary to truly make
* this utility a standalone one.
*/
/****************************************************************************/
/* Number of timers initially in Timer object. */
#define INITLENGTH 30
/* Length of character strings naming each timer. */
/* If you change this constant, change the string format */
/* in Zoltan_Timer_Print, too. */
#define MAXNAMELEN 31
/* Flag indicating whether a timer is in use. */
#define INUSE 1
/* Flag indicating whether a timer is running. */
#define RUNNING 2
#define FATALERROR(yo, str) \
{ \
int ppproc; \
MPI_Comm_rank(MPI_COMM_WORLD, &ppproc); \
ZOLTAN_PRINT_ERROR(ppproc, yo, str); \
return ZOLTAN_FATAL; \
}
/* Macro to ensure that a Timer object is non-NULL */
#define TESTTIMER(zt, yo) \
if ((zt) == NULL) FATALERROR(yo, "NULL Zoltan_Timer")
/* Macro to ensure that a given timer index is valid. */
#define TESTINDEX(zt, ts_idx, yo) \
if ((ts_idx) >= (zt)->NextTimeStruct) FATALERROR(yo, "Invalid Timer Index")
/****************************************************************************/
/* Structure that implements an individual timer. */
typedef struct TimeStruct {
double Start_Time; /* Most recent start time;
set by Zoltan_Timer_Start */
double Stop_Time; /* Most recent end time;
set by Zoltan_Timer_Stop */
char Start_File[MAXNAMELEN+1]; /* Filename for most recent Start */
char Stop_File[MAXNAMELEN+1]; /* Filename for most recent Stop */
int Start_Line; /* Line # in Start_File for most recent Start */
int Stop_Line; /* Line # in Stop_File for most recent Stop */
double My_Tot_Time; /* Sum of stop_time-start_time over all invocations
of this timer */
int Use_Barrier; /* Flag indicating whether to perform a barrier
operation before starting the timer. */
int Status; /* Flag indicating status of TimeStruct:
> 0 --> In Use
> 2 --> Running */
char Name[MAXNAMELEN+1];/* String associated (and printed) with timer info */
#ifdef VAMPIR
int vt_handle; /* state handle for vampir traces */
#endif
} ZTIMER_TS;
/* Timer object consisting of many related timers.
* Applications access this structure. */
typedef struct Zoltan_Timer {
int Timer_Flag; /* Zoltan Timer_Flag flag passed to Zoltan_Time */
int Length; /* # of entries allocated in Times */
int NextTimeStruct; /* Index of next unused TimeStruct */
ZTIMER_TS *Times; /* Array of actual timing data -- individual timers */
} ZTIMER;
/****************************************************************************/
ZTIMER *Zoltan_Timer_Copy(ZTIMER *from)
{
ZTIMER *to = NULL;
Zoltan_Timer_Copy_To(&to, from);
return to;
}
/****************************************************************************/
int Zoltan_Timer_Copy_To(ZTIMER **to, ZTIMER *from)
{
ZTIMER *toptr = NULL;
if (!to){
return ZOLTAN_FATAL;
}
if (*to){
Zoltan_Timer_Destroy(to);
}
if (from){
*to = (ZTIMER *)ZOLTAN_MALLOC(sizeof(ZTIMER));
toptr = *to;
toptr->Timer_Flag = from->Timer_Flag;
toptr->Length = from->Length;
toptr->NextTimeStruct = from->NextTimeStruct;
if (toptr->Length > 0){
toptr->Times = (ZTIMER_TS *)ZOLTAN_MALLOC(sizeof(ZTIMER_TS) * toptr->Length);
memcpy(toptr->Times, from->Times, sizeof(ZTIMER_TS) * toptr->Length);
}
else{
toptr->Times = NULL;
}
}
return ZOLTAN_OK;
}
/****************************************************************************/
ZTIMER *Zoltan_Timer_Create(
int timer_flag
)
{
/* Allocates a Timer object for the application; returns a pointer to it.
* Does not start any timers.
*/
ZTIMER *zt;
int i;
zt = (ZTIMER *) ZOLTAN_MALLOC(sizeof(ZTIMER));
zt->Times = (ZTIMER_TS *) ZOLTAN_MALLOC(sizeof(ZTIMER_TS) * INITLENGTH);
zt->Timer_Flag = timer_flag;
zt->Length = INITLENGTH;
zt->NextTimeStruct = 0;
for (i = 0; i < zt->Length; i++)
zt->Times[i].Status = 0;
return zt;
}
/****************************************************************************/
int Zoltan_Timer_Init(
ZTIMER *zt, /* Ptr to Timer object */
int use_barrier, /* Flag indicating whether to perform a
barrier operation before starting the
timer. */
const char *name /* Name of this timer */
)
{
/* Function that returns the index of the next available Timer timer. */
int ret;
static char *yo = "Zoltan_Timer_Init";
TESTTIMER(zt, yo);
ret = zt->NextTimeStruct++;
if (ret >= zt->Length) {
/* Realloc -- need more individual timers */
zt->Length += INITLENGTH;
zt->Times = (ZTIMER_TS *) ZOLTAN_REALLOC(zt->Times, zt->Length * sizeof(ZTIMER_TS));
}
Zoltan_Timer_Reset(zt, ret, use_barrier, name);
#ifdef VAMPIR
if (VT_funcdef(name, VT_NOCLASS, &((zt->Times[ret]).vt_handle)) != VT_OK)
FATALERROR(yo, "VT_funcdef failed.");
#endif
return ret;
}
/****************************************************************************/
int Zoltan_Timer_Reset(
ZTIMER *zt,
int ts_idx, /* Index of the timer to reset */
int use_barrier, /* Flag indicating whether to perform a
barrier operation before starting the
timer. */
const char *name /* Name of this timer */
)
{
/* Initialize a timer for INUSE; reset its values to zero. */
static char *yo = "Zoltan_Timer_Reset";
ZTIMER_TS *ts;
TESTTIMER(zt, yo);
TESTINDEX(zt, ts_idx, yo);
ts = &(zt->Times[ts_idx]);
ts->Status = INUSE;
ts->Start_Time = 0.;
ts->Stop_Time = 0.;
ts->My_Tot_Time = 0.;
ts->Use_Barrier = use_barrier;
strncpy(ts->Name, name, MAXNAMELEN);
ts->Name[MAXNAMELEN] = '\0';
ts->Start_File[0] = '\0';
ts->Start_Line = -1;
ts->Stop_File[0] = '\0';
ts->Stop_Line = -1;
return ZOLTAN_OK;
}
/****************************************************************************/
int Zoltan_Timer_ChangeFlag(
ZTIMER *zt,
int timer
)
{
static char *yo = "Zoltan_Timer_ChangeFlag";
TESTTIMER(zt, yo);
zt->Timer_Flag = timer;
return ZOLTAN_OK;
}
/****************************************************************************/
int Zoltan_Timer_Start(
ZTIMER *zt, /* Ptr to Timer object */
int ts_idx, /* Index of the timer to use */
MPI_Comm comm, /* Communicator to use for synchronization,
if requested */
char *filename, /* Filename of file calling the Start */
int lineno /* Line number where Start was called */
)
{
ZTIMER_TS *ts;
static char *yo = "Zoltan_Timer_Start";
TESTTIMER(zt, yo);
TESTINDEX(zt, ts_idx, yo);
ts = &(zt->Times[ts_idx]);
if (ts->Status > RUNNING) {
char msg[256];
sprintf(msg,
"Cannot start timer %d at %s:%d; timer already running from %s:%d.",
ts_idx, filename, lineno, ts->Start_File, ts->Start_Line);
FATALERROR(yo, msg)
}
ts->Status += RUNNING;
strncpy(ts->Start_File, filename, MAXNAMELEN);
ts->Start_Line = lineno;
if (ts->Use_Barrier)
MPI_Barrier(comm);
ts->Start_Time = Zoltan_Time(zt->Timer_Flag);
#ifdef VAMPIR
if (VT_begin(ts->vt_handle) != VT_OK)
FATALERROR(yo, "VT_begin failed.");
#endif
return ZOLTAN_OK;
}
/****************************************************************************/
int Zoltan_Timer_Stop(
ZTIMER *zt, /* Ptr to Timer object */
int ts_idx, /* Index of the timer to use */
MPI_Comm comm, /* Communicator to use for synchronization,
if requested */
char *filename, /* Filename of file calling the Stop */
int lineno /* Line number where Stop was called */
)
{
/* Function to stop a timer and accrue its information */
ZTIMER_TS *ts;
static char *yo = "Zoltan_Timer_Stop";
double my_time;
TESTTIMER(zt, yo);
TESTINDEX(zt, ts_idx, yo);
ts = &(zt->Times[ts_idx]);
if (ts->Status < RUNNING) {
if (ts->Stop_Line == -1)
FATALERROR(yo, "Cannot stop timer; timer never started.")
else {
char msg[256];
sprintf(msg,
"Cannot stop timer %d at %s:%d; "
"timer already stopped from %s:%d.",
ts_idx, filename, lineno, ts->Stop_File, ts->Stop_Line);
FATALERROR(yo, msg)
}
}
#ifdef VAMPIR
if (VT_end(ts->vt_handle) != VT_OK)
FATALERROR(yo, "VT_end failed.");
#endif
if (ts->Use_Barrier)
MPI_Barrier(comm);
ts->Stop_Time = Zoltan_Time(zt->Timer_Flag);
ts->Status -= RUNNING;
ts->Stop_Line = lineno;
strncpy(ts->Stop_File, filename, MAXNAMELEN);
my_time = ts->Stop_Time - ts->Start_Time;
ts->My_Tot_Time += my_time;
return ZOLTAN_OK;
}
/****************************************************************************/
int Zoltan_Timer_Print(
ZTIMER *zt,
int ts_idx,
int proc, /* Rank of the processor (in comm) that should print the data. */
MPI_Comm comm,
FILE *fp
)
{
/* Accrues a single timer's values across a communicator and prints
* its information. This function must be called by all processors
* within the communicator.
*/
static char *yo = "Zoltan_Timer_Print";
ZTIMER_TS *ts;
int my_proc, nproc;
int restart = 0;
double max_time;
double min_time;
double sum_time;
TESTTIMER(zt, yo);
TESTINDEX(zt, ts_idx, yo);
MPI_Comm_rank(comm, &my_proc);
MPI_Comm_size(comm, &nproc);
ts = &(zt->Times[ts_idx]);
if (ts->Status > RUNNING) {
/* Timer is running; stop it before printing the times.
* Don't want to include print times in timer.
*/
restart = 1;
ZOLTAN_TIMER_STOP(zt, ts_idx, comm);
}
MPI_Allreduce(&(ts->My_Tot_Time), &max_time, 1, MPI_DOUBLE, MPI_MAX, comm);
MPI_Allreduce(&(ts->My_Tot_Time), &min_time, 1, MPI_DOUBLE, MPI_MIN, comm);
MPI_Allreduce(&(ts->My_Tot_Time), &sum_time, 1, MPI_DOUBLE, MPI_SUM, comm);
if (proc == my_proc)
fprintf(fp,
"%3d ZOLTAN_TIMER %3d %23s: MyTime %7.4f "
"MaxTime %7.4f MinTime %7.4f AvgTime %7.4f\n",
proc, ts_idx, ts->Name, ts->My_Tot_Time,
max_time, min_time, sum_time/nproc);
if (restart) {
/* We stopped the timer for printing; restart it now. */
ZOLTAN_TIMER_START(zt, ts_idx, comm);
}
return ZOLTAN_OK;
}
/****************************************************************************/
int Zoltan_Timer_PrintAll(
ZTIMER *zt,
int proc, /* Rank of the processor (in comm) that should print the data. */
MPI_Comm comm,
FILE *fp
)
{
/* Function to print all timer information */
static char *yo = "Zoltan_Timer_PrintAll";
int i, ierr = ZOLTAN_OK;
TESTTIMER(zt, yo);
for (i = 0; i < zt->NextTimeStruct; i++)
if ((ierr = Zoltan_Timer_Print(zt, i, proc, comm, fp)) != ZOLTAN_OK)
break;
return ierr;
}
/****************************************************************************/
void Zoltan_Timer_Destroy(
ZTIMER **zt
)
{
/* Destroy a Timer object */
if (*zt != NULL) {
ZOLTAN_FREE(&((*zt)->Times));
ZOLTAN_FREE(zt);
}
}
/****************************************************************************/
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,83 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#include <stddef.h>
#include "zoltan_align.h"
#include "zoltan_util.h"
/*****************************************************************************/
/*
* Routines for properly aligning data.
*/
/*****************************************************************************/
/*
* Plauger alignment algorithm, The Standard C Library.
* Forces malloc'ed variable size struct alignment.
* ZOLTAN_ALIGN_VAL is defined in Zoltan/include/zoltan_align.h;
* values are 0,1,3,7U depending upon machine.
*/
int Zoltan_Align(int a)
{
return((ZOLTAN_ALIGN_VAL + a) & ~ZOLTAN_ALIGN_VAL);
}
size_t Zoltan_Align_size_t(size_t a)
{
return((ZOLTAN_ALIGN_VAL + a) & ~ZOLTAN_ALIGN_VAL);
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,192 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#include <stdio.h>
#include "zoltan_types.h"
#include "zoltan_id.h"
#include "zoltan_util.h"
#include "zoltan_mem.h"
/*****************************************************************************/
/*
* This file contains routines for manipulating
* the global and local IDs used by Zoltan.
*
* Some manipulations are performed via macros. In particular, macros
* specifying whether global or local IDs are to be manipulated are
* provided. Use of these macros is recommended over use of these
* basic functions.
* See zoltan_id.h for definitions of these macros.
*/
/*****************************************************************************/
/*****************************************************************************/
/*
* Routines for allocating and initializing IDs.
*/
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;
}
/*****************************************************************************/
/*****************************************************************************/
/*
* Routines for printing IDs.
*/
void ZOLTAN_PRINT_ID(int n, ZOLTAN_ID_PTR a)
{
/* Prints a single ID. */
int i;
printf("(");
for (i = 0; i < n; i++)
printf( ZOLTAN_ID_SPEC " ",a[i]);
printf(") ");
}
/*****************************************************************************/
/*****************************************************************************/
/*
* Routines to compare Global IDs.
* Functions are provided to test whether two IDs are equal (EQ),
* less than (LT), and greater than (GT).
* The negation operator can be used to test whether two IDs are
* not equal (!ZOLTAN_EQ_ID(n,a,b)), less than or equal (!ZOLTAN_GT_GID(n,a,b))
* or greater than or equal (!ZOLTAN_LT_GID(n,a,b)).
*/
/*****************************************************************************/
int ZOLTAN_EQ_ID(int n, ZOLTAN_ID_PTR a, ZOLTAN_ID_PTR b)
{
/*
* Returns 1 if a == b; 0 otherwise.
* a == b if for all i, a[i] == b[i].
*/
int i;
for (i = 0; i < n; i++)
if (a[i] != b[i])
return(0);
return(1);
}
/*****************************************************************************/
#ifdef ZOLTAN_NEEDED
/* Commented out since never used. */
int ZOLTAN_LT_ID(int n, ZOLTAN_ID_PTR a, ZOLTAN_ID_PTR b)
{
/*
* Returns 1 if a < b; 0 otherwise.
* a < b if for some i, a[i] < b[i] and a[j] == b[j] for all j < i.
*/
int i;
for (i = 0; i < n; i++)
if (a[i] == b[i])
continue;
else if (a[i] > b[i])
return(0);
else /* a[i] < b[i] */
return(1);
return(0); /* because a == b */
}
/*****************************************************************************/
int ZOLTAN_GT_ID(int n, ZOLTAN_ID_PTR a, ZOLTAN_ID_PTR b)
{
/*
* Returns 1 if a < b; 0 otherwise.
* a > b if for some i, a[i] > b[i] and a[j] == b[j] for all j < i.
*/
int i;
for (i = 0; i < n; i++)
if (a[i] == b[i])
continue;
else if (a[i] < b[i])
return(0);
else /* a[i] > b[i] */
return(1);
return(0); /* because a == b */
}
#endif /* ZOLTAN_NEEDED */
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

View File

@ -0,0 +1,109 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef __ZOLTAN_ID_H
#define __ZOLTAN_ID_H
#include "zoltan_types.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/*
* This file contains the data types and comparison functions
* for IDs used by Zoltan and its Utilities. The basic data type
* is ZOLTAN_ID.
*/
/****************************************************************************/
/*
* Default value of ZOLTAN_ID_TYPE;
* IDs allocated with ZOLTAN_MALLOC_ID are initialized with this value.
*/
#define ZOLTAN_ID_DEFAULT 0
/*
* Macros for initializing single IDs.
*/
#define ZOLTAN_INIT_ID(n,id) \
{int ZOLTAN_ID_LOOP; \
for (ZOLTAN_ID_LOOP = 0; ZOLTAN_ID_LOOP < (n); ZOLTAN_ID_LOOP++) \
(id)[ZOLTAN_ID_LOOP] = ZOLTAN_ID_DEFAULT; \
}
/****************************************************************************/
/*
* Macros to copy IDs.
*/
#define ZOLTAN_SET_ID(n,a,b) \
{int ZOLTAN_ID_LOOP; \
for (ZOLTAN_ID_LOOP = 0; ZOLTAN_ID_LOOP < (n); ZOLTAN_ID_LOOP++) \
(a)[ZOLTAN_ID_LOOP] = (b)[ZOLTAN_ID_LOOP]; \
}
/****************************************************************************/
/*
* Prototypes for ID functions in id.c
*/
extern ZOLTAN_ID_PTR ZOLTAN_Malloc_ID(int n, char *file, int line);
extern void ZOLTAN_PRINT_ID(int n, ZOLTAN_ID_PTR a);
extern int ZOLTAN_EQ_ID(int n, ZOLTAN_ID_PTR a, ZOLTAN_ID_PTR b);
#ifdef ZOLTAN_NEEDED
/* Commented out since never used */
extern int ZOLTAN_LT_ID(int n, ZOLTAN_ID_PTR a, ZOLTAN_ID_PTR b);
extern int ZOLTAN_GT_ID(int n, ZOLTAN_ID_PTR a, ZOLTAN_ID_PTR b);
#endif /* ZOLTAN_NEEDED */
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif
#endif

View File

@ -0,0 +1,188 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef __ZOLTAN_UTIL_H
#define __ZOLTAN_UTIL_H
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* This block should be executed for Autotools and CMake builds. */
/* The Zoltan classic build defines TRILINOS_NO_CONFIG_H. */
#ifndef TRILINOS_NO_CONFIG_H
#ifdef PACKAGE
#undef PACKAGE
#endif
#ifdef PACKAGE_NAME
#undef PACKAGE_NAME
#endif
#ifdef PACKAGE_BUGREPORT
#undef PACKAGE_BUGREPORT
#endif
#ifdef PACKAGE_STRING
#undef PACKAGE_STRING
#endif
#ifdef PACKAGE_TARNAME
#undef PACKAGE_TARNAME
#endif
#ifdef PACKAGE_VERSION
#undef PACKAGE_VERSION
#endif
#ifdef VERSION
#undef VERSION
#endif
/* This file passes values from configure to the source code. */
#include "Zoltan_config.h"
#ifdef HAVE_PARMETIS
#define ZOLTAN_PARMETIS
#endif
#ifdef HAVE_METIS
#define ZOLTAN_METIS
#endif
#ifdef HAVE_SCOTCH
#define ZOLTAN_SCOTCH
# ifdef HAVE_MPI
# define ZOLTAN_PTSCOTCH
# endif
#endif
#ifdef HAVE_OVIS
#define ZOLTAN_OVIS
#endif
#ifdef HAVE_PATOH
#define ZOLTAN_PATOH
#endif
#ifdef HAVE_CCOLAMD
#define ZOLTAN_CCOLAMD
#endif
#ifdef HAVE_ZOLTAN_HUND
#define ZOLTAN_HUND
#endif
#ifdef HAVE_PARKWAY
#define ZOLTAN_PARKWAY
#endif
#ifdef HAVE_PURIFY
#define ZOLTAN_PURIFY
#define strcmp Zoltan_strcmp
#define strncmp Zoltan_strncmp
#define strcasecmp Zoltan_strcasecmp
#define strncasecmp Zoltan_strncasecmp
#endif
#else /* !AUTOTOOLS_BUILD */
/* With the manual build system we support only Parallel Version of Scotch */
#ifdef ZOLTAN_SCOTCH
#define ZOLTAN_PTSCOTCH
#endif
#endif /* !AUTOTOOLS_BUILD */
/*****************************************************************************/
/*
* Macros and definitions that are common to all Zoltan modules and
* utilities.
*/
/*****************************************************************************/
/*****************************************************************************/
/*
* Macros for consistently printing error and warning messages.
*/
/*****************************************************************************/
void Zoltan_add_back_trace(char *yo);
void Zoltan_remove_back_trace();
void Zoltan_print_trace(int rank);
#define ZOLTAN_PRINT_ERROR(proc,yo,str) { \
fprintf(stderr, "[%d] Zoltan ERROR in %s (line %d of %s): %s\n", \
proc, yo, __LINE__, __FILE__, str); \
Zoltan_print_trace(proc); }
#define ZOLTAN_PRINT_WARN(proc,yo,str) \
fprintf(stderr, "[%d] Zoltan WARNING in %s (line %d of %s): %s\n", \
proc, yo, __LINE__, __FILE__, str);
#define ZOLTAN_TRACE(proc,where,yo,str) \
printf("ZOLTAN (Processor %d) %s %s %s\n", (proc), (where), (yo), \
((str) != NULL ? (char *)(str) : " "));
#define ZOLTAN_TRACE_IN(proc,yo,str) \
ZOLTAN_TRACE((proc),"Entering",(yo),(str));
#define ZOLTAN_TRACE_OUT(proc,yo,str) \
ZOLTAN_TRACE((proc),"Exiting",(yo),(str));
#define ZOLTAN_PRINT_INFO(proc,yo,str) \
printf("ZOLTAN (Processor %d) %s: %s\n", (proc), (yo), \
((str) != NULL ? (char *)(str) : " "));
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif
#endif /* !__ZOLTAN_UTIL_H */