Ejemplo n.º 1
0
/*
  MPIR_Topology_copy_fn - copies topology information.
 */
int MPIR_Topology_copy_fn(
	MPI_Comm old_comm, 
	int keyval, 
	void *extra, 
	void *attr_in, 
	void *attr_out, 
	int *flag)
{
  MPIR_TOPOLOGY *old_topo = (MPIR_TOPOLOGY *) attr_in;
  MPIR_TOPOLOGY *new_topo = (MPIR_TOPOLOGY *) MPIR_SBalloc ( MPIR_topo_els );

  if (!new_topo)
      return MPI_ERR_EXHAUSTED;

  /* Copy topology info */
  new_topo->type = old_topo->type;
  if (old_topo->type == MPI_CART) {
    int i, ndims;
    MPIR_SET_COOKIE(&new_topo->cart,MPIR_CART_TOPOL_COOKIE)
    new_topo->cart.nnodes        = old_topo->cart.nnodes; 
    new_topo->cart.ndims = ndims = old_topo->cart.ndims;
    new_topo->cart.dims          = (int *)MALLOC( sizeof(int) * 3 * ndims );
    if (!new_topo) return MPI_ERR_EXHAUSTED;
    new_topo->cart.periods       = new_topo->cart.dims + ndims;
    new_topo->cart.position      = new_topo->cart.periods + ndims;
    for ( i=0; i<ndims; i++ ) {
      new_topo->cart.dims[i]     = old_topo->cart.dims[i];
      new_topo->cart.periods[i]  = old_topo->cart.periods[i];
    }
    for ( i=0; i < ndims; i++ ) 
      new_topo->cart.position[i] = old_topo->cart.position[i];
  }
  else if (old_topo->type == MPI_GRAPH) {
    int  i, nnodes;
    int *index;
    MPIR_SET_COOKIE(&new_topo->graph,MPIR_GRAPH_TOPOL_COOKIE)
    new_topo->graph.nnodes = nnodes = old_topo->graph.nnodes;
    new_topo->graph.nedges        = old_topo->graph.nedges;
    index = old_topo->graph.index;
    new_topo->graph.index         = 
      (int *)MALLOC(sizeof(int) * (nnodes + index[nnodes-1]) );
    if (!new_topo->graph.index) return MPI_ERR_EXHAUSTED;
    new_topo->graph.edges         = new_topo->graph.index + nnodes;
    for ( i=0; i<nnodes; i++ )
      new_topo->graph.index[i]    = old_topo->graph.index[i];
    for ( i=0; i<index[nnodes-1]; i++ )
      new_topo->graph.edges[i]    = old_topo->graph.edges[i];
  }

  /* Set attr_out and return a "1" to indicate information was copied */
  (*(void **)attr_out) = (void *) new_topo;
  (*flag)     = 1;
  return (MPI_SUCCESS);
}
Ejemplo n.º 2
0
void MPID_Request_init (MPI_Request rq, MPIR_OPTYPE rq_type)
{
    MPID_Device *dev = NULL;

    rq->chandle.handle_type = rq_type;
    rq->chandle.ref_count   = 1;
    MPIR_SET_COOKIE(&(rq->chandle), MPIR_REQUEST_COOKIE);
    

    /* For persistent communication, the device may need to perform
       additional actions. */
    switch (rq->handle_type) {
    case MPIR_SEND:
	break;
    case MPIR_RECV:
	break;
    case MPIR_PERSISTENT_SEND:
	dev = MPID_devset->dev[((rq->persistent_shandle.perm_comm)->lrank_to_grank)
			      [rq->persistent_shandle.perm_dest]];
	
	if (dev->persistent_init != NULL)
	  MPID_Device_call_persistent_init (rq, dev);
	break;
    case MPIR_PERSISTENT_RECV: 
	if (rq->persistent_rhandle.perm_source >= 0) {
	    dev = MPID_devset->dev[rq->persistent_rhandle.perm_source];
	} else {
	    /* For a single device, we can use the related function, 
	       but what to do for multiple available devices? Multiple
	       persistent initialization? */
	    if (MPID_devset->ndev == 1) {
		dev = MPID_devset->dev_list;
	    }
	}

	if (dev != NULL && dev->persistent_init != NULL)
	  MPID_Device_call_persistent_init (rq, dev);
	break;
    }
    
    return;
}
Ejemplo n.º 3
0
/*@

MPI_Group_union - Produces a group by combining two groups

Input Parameters:
+ group1 - first group (handle) 
- group2 - second group (handle) 

Output Parameter:
. newgroup - union group (handle) 

.N fortran

.N Errors
.N MPI_SUCCESS
.N MPI_ERR_GROUP
.N MPI_ERR_EXHAUSTED

.seealso: MPI_Group_free
@*/
EXPORT_MPI_API int MPI_Group_union ( MPI_Group group1, MPI_Group group2, 
		      MPI_Group *group_out )
{
  int        i, j, global_rank;
  struct MPIR_GROUP *group1_ptr, *group2_ptr, *new_group_ptr;
  int        n;
  int        mpi_errno = MPI_SUCCESS;
  static char myname[] = "MPI_GROUP_UNION";

  TR_PUSH(myname);

  group1_ptr = MPIR_GET_GROUP_PTR(group1);

  group2_ptr = MPIR_GET_GROUP_PTR(group2);
/*  MPIR_TEST_MPI_GROUP(group1,group1_ptr,MPIR_COMM_WORLD,myname);
  MPIR_TEST_MPI_GROUP(grou2p,group2_ptr,MPIR_COMM_WORLD,myname); */

#ifndef MPIR_NO_ERROR_CHECKING
  MPIR_TEST_GROUP(group1_ptr);
  MPIR_TEST_GROUP(group2_ptr);
    if (mpi_errno)
	return MPIR_ERROR(MPIR_COMM_WORLD, mpi_errno, myname );
#endif

  /* Check for EMPTY groups */
  if ( (group1 == MPI_GROUP_EMPTY) && (group2 == MPI_GROUP_EMPTY) ) {
      MPIR_Group_dup ( MPIR_GROUP_EMPTY, &new_group_ptr );
      TR_POP;
      *group_out = new_group_ptr->self;
      return (mpi_errno);
  }
  if ( group1 == MPI_GROUP_EMPTY ) {
    MPIR_Group_dup ( group2_ptr, &new_group_ptr );
    *group_out = new_group_ptr->self;
    TR_POP;
    return (mpi_errno);
  }
  if ( group2 == MPI_GROUP_EMPTY ) {
    MPIR_Group_dup ( group1_ptr, &new_group_ptr );
    *group_out = new_group_ptr->self;
    TR_POP;
    return (mpi_errno);
  }
  
  /* Create the new group */
  MPIR_ALLOC(new_group_ptr,NEW(struct MPIR_GROUP),MPIR_COMM_WORLD, 
	     MPI_ERR_EXHAUSTED, "MPI_GROUP_UNION" );
  *group_out	      = (MPI_Group) MPIR_FromPointer( new_group_ptr );
  new_group_ptr->self = *group_out;
  MPIR_SET_COOKIE(new_group_ptr,MPIR_GROUP_COOKIE)
  new_group_ptr->ref_count	= 1;
  new_group_ptr->permanent	= 0;
  new_group_ptr->local_rank	= group1_ptr->local_rank;
  new_group_ptr->set_mark	= (int *)0;
  
  /* Set the number in the union */
  n = group1_ptr->np + group2_ptr->np;

  /* Allocate set marking space for group2 if necessary */
  if (group2_ptr->set_mark == NULL) {
      MPIR_ALLOC(group2_ptr->set_mark,(int *) MALLOC( group2_ptr->np * sizeof(int) ),
		 MPIR_COMM_WORLD,MPI_ERR_EXHAUSTED,"MPI_GROUP_UNION");
  }

  /* Mark the union */
  for ( j=0; j<group2_ptr->np; j++ ) {
    group2_ptr->set_mark[j] = MPIR_MARKED;
    for ( i=0; i<group1_ptr->np; i++ ) 
      if ( group1_ptr->lrank_to_grank[i] == group2_ptr->lrank_to_grank[j] ) {
        group2_ptr->set_mark[j] = MPIR_UNMARKED;
        n--;
        break;
      }
  }
  
  /* Alloc the memory */
  new_group_ptr->np             = n;
  MPIR_ALLOC(new_group_ptr->lrank_to_grank,(int *) MALLOC( n * sizeof(int) ),
	     MPIR_COMM_WORLD, MPI_ERR_EXHAUSTED, 
	     "MPI_GROUP_UNION" );
  
  /* Fill in the space */
  n = group1_ptr->np;
  memcpy(new_group_ptr->lrank_to_grank,group1_ptr->lrank_to_grank,n*sizeof(int));
  for ( j=0; j<group2_ptr->np; j++ ) 
    if ( (group2_ptr->set_mark[j]==MPIR_MARKED) && (n < new_group_ptr->np) ) 
      new_group_ptr->lrank_to_grank[n++] = group2_ptr->lrank_to_grank[j];
  
  /* Find the local rank only if local rank not defined in group 1 */
  if ( new_group_ptr->local_rank == MPI_UNDEFINED ) {
      global_rank = MPID_MyWorldRank;
      for( i=group1_ptr->np; i<new_group_ptr->np; i++ )
	  if ( global_rank == new_group_ptr->lrank_to_grank[i] ) {
	      new_group_ptr->local_rank = i;
	      break;
	  }
  }
  
  /* Determine the previous and next powers of 2 */
  MPIR_Powers_of_2 ( new_group_ptr->np, &(new_group_ptr->N2_next), &(new_group_ptr->N2_prev) );

  TR_POP;
  return (mpi_errno);
}
Ejemplo n.º 4
0
/*@
    MPI_Type_struct - Creates a struct datatype

Input Parameters:
+ count - number of blocks (integer) -- also number of 
entries in arrays array_of_types ,
array_of_displacements  and array_of_blocklengths  
. blocklens - number of elements in each block (array)
. indices - byte displacement of each block (array)
- old_types - type of elements in each block (array 
of handles to datatype objects) 

Output Parameter:
. newtype - new datatype (handle) 

Notes:
If an upperbound is set explicitly by using the MPI datatype 'MPI_UB', the
corresponding index must be positive.

The MPI standard originally made vague statements about padding and alignment;
this was intended to allow the simple definition of structures that could
be sent with a count greater than one.  For example,
.vb
    struct { int a; char b; } foo;
.ve
may have 'sizeof(foo) > sizeof(int) + sizeof(char)'; for example, 
'sizeof(foo) == 2*sizeof(int)'.  The initial version of the MPI standard
defined the extent of a datatype as including an `epsilon` that would have 
allowed an implementation to make the extent an MPI datatype
for this structure equal to '2*sizeof(int)'.  
However, since different systems might define different paddings, there was 
much discussion by the MPI Forum about what was the correct value of
epsilon, and one suggestion was to define epsilon as zero.
This would have been the best thing to do in MPI 1.0, particularly since 
the 'MPI_UB' type allows the user to easily set the end of the structure.
Unfortunately, this change did not make it into the final document.  
Currently, this routine does not add any padding, since the amount of 
padding needed is determined by the compiler that the user is using to
build their code, not the compiler used to construct the MPI library.
A later version of MPICH may provide for some natural choices of padding
(e.g., multiple of the size of the largest basic member), but users are
advised to never depend on this, even with vendor MPI implementations.
Instead, if you define a structure datatype and wish to send or receive
multiple items, you should explicitly include an 'MPI_UB' entry as the
last member of the structure.  For example, the following code can be used
for the structure foo
.vb
    blen[0] = 1; indices[0] = 0; oldtypes[0] = MPI_INT;
    blen[1] = 1; indices[1] = &foo.b - &foo; oldtypes[1] = MPI_CHAR;
    blen[2] = 1; indices[2] = sizeof(foo); oldtypes[2] = MPI_UB;
    MPI_Type_struct( 3, blen, indices, oldtypes, &newtype );
.ve

.N fortran

.N Errors
.N MPI_SUCCESS
.N MPI_ERR_TYPE
.N MPI_ERR_COUNT
.N MPI_ERR_EXHAUSTED
@*/
int MPI_Type_struct( 
	int count, 
	int blocklens[], 
	MPI_Aint indices[], 
	MPI_Datatype old_types[], 
	MPI_Datatype *newtype )
{
  struct MPIR_DATATYPE* dteptr;
  MPI_Aint        ub, lb, high, low, real_ub, real_lb, real_init;
  int             high_init = 0, low_init = 0;
  int             i, mpi_errno = MPI_SUCCESS;
  MPI_Aint        ub_marker = 0, lb_marker = 0; /* to suppress warnings */
  MPI_Aint        ub_found = 0, lb_found = 0;
  int             size, total_count;
  static char myname[] = "MPI_TYPE_STRUCT";

  disableSignal();

  /* Check for bad arguments */
  if ( count < 0 ) {
	mpi_errno = MPIR_Err_setmsg( MPI_ERR_COUNT, MPIR_ERR_DEFAULT, myname,
				   (char *)0, (char *)0, count );
        revertSignal();
	return MPIR_ERROR( MPIR_COMM_WORLD, mpi_errno, myname );
  }

  if (count == 0) {
      revertSignal();
      return MPI_Type_contiguous( 0, MPI_INT, newtype );
  }

  /* Check blocklens and old_types arrays and find number of bound */
  /* markers */
  total_count = 0;
  for (i=0; i<count; i++) {
    total_count += blocklens[i];
    if ( blocklens[i] < 0) {
	mpi_errno = MPIR_Err_setmsg( MPI_ERR_ARG, MPIR_ERR_ARG_ARRAY_VAL,
				     myname, (char *)0, (char *)0,
				     "blocklens", i, blocklens[i] );
        revertSignal();
	return MPIR_ERROR( MPIR_COMM_WORLD, mpi_errno,myname);
    }
    if ( old_types[i] == MPI_DATATYPE_NULL ) {
	mpi_errno = MPIR_Err_setmsg( MPI_ERR_TYPE, MPIR_ERR_TYPE_ARRAY_NULL,
				     myname, (char *)0, (char *)0, 
				     "old_types", i );
      revertSignal();
      return MPIR_ERROR( MPIR_COMM_WORLD, mpi_errno, myname );
    }
  }
  if (total_count == 0) {
      revertSignal();
      return MPI_Type_contiguous( 0, MPI_INT, newtype );
  }

  /* Create and fill in the datatype */
  MPIR_ALLOC(dteptr,(struct MPIR_DATATYPE *) MPIR_SBalloc( MPIR_dtes ),MPIR_COMM_WORLD, 
	     MPI_ERR_EXHAUSTED, myname );
  *newtype = (MPI_Datatype) MPIR_FromPointer( dteptr );
  dteptr->self = *newtype;
  MPIR_SET_COOKIE(dteptr,MPIR_DATATYPE_COOKIE)
  dteptr->dte_type    = MPIR_STRUCT;
  dteptr->committed   = 0;
  dteptr->basic       = 0;
  dteptr->permanent   = 0;
  dteptr->is_contig   = 0;
  dteptr->ref_count   = 1;
  dteptr->count       = count;
  dteptr->elements    = 0;
  dteptr->size        = 0;
  dteptr->align       = 1;
  dteptr->has_ub      = 0;
  dteptr->has_lb      = 0;
  dteptr->self        = *newtype;

  /* Create indices and blocklens arrays and fill them */
  dteptr->indices     = ( MPI_Aint * ) MALLOC( count * sizeof( MPI_Aint ) );
  dteptr->blocklens   = ( int * )      MALLOC( count * sizeof( int ) );
  dteptr->old_types   =
       ( struct MPIR_DATATYPE ** )MALLOC(count*sizeof(struct MPIR_DATATYPE *));
  if (!dteptr->indices || !dteptr->blocklens || !dteptr->old_types) {
      revertSignal();
      return MPIR_ERROR( MPIR_COMM_WORLD, MPI_ERR_EXHAUSTED, 
			 "MPI_TYPE_STRUCT" );
  }
  high = low = ub = lb = 0;
  real_ub   = real_lb = 0;
  real_init = 0;

/* If data alignment is 2, 4, or 8, then assign dteptr->align to that
   value.  If 0, then assign dteptr->align to the maximal alignment 
   requirement. (done below) */
  if (ALIGNMENT_VALUE > 0)
      dteptr->align = ALIGNMENT_VALUE;

  for (i = 0; i < count; i++)  {
      struct MPIR_DATATYPE *old_dtype_ptr;

      old_dtype_ptr   = MPIR_GET_DTYPE_PTR(old_types[i]);
      MPIR_TEST_DTYPE(old_types[i],old_dtype_ptr,MPIR_COMM_WORLD,
		      "MPI_TYPE_STRUCT");
      dteptr->old_types[i]  = MPIR_Type_dup (old_dtype_ptr);
      dteptr->indices[i]    = indices[i];
      dteptr->blocklens[i]  = blocklens[i];

      /* Keep track of maximal alignment requirement */
      if (ALIGNMENT_VALUE == 0) {
	  if (dteptr->align < old_dtype_ptr->align)
	      dteptr->align       = old_dtype_ptr->align; 
      }
      if ( old_dtype_ptr->dte_type == MPIR_UB ) {
	  if (ub_found) {
	      if (indices[i] > ub_marker)
		  ub_marker = indices[i];
	      }
	  else {
	      ub_marker = indices[i];
	      ub_found  = 1;
	      }
	  }
      else if ( old_dtype_ptr->dte_type == MPIR_LB ) {
	   if (lb_found) { 
	      if ( indices[i] < lb_marker ) {
		  lb_marker = indices[i];
	      }
	  }
	  else {
	      lb_marker = indices[i];
	      lb_found  = 1;
	      }
	  }
      else {
	  /* Since the datatype is NOT a UB or LB, save the real limits */
	  if (!real_init) {
	      real_init = 1;
	      real_lb = old_dtype_ptr->real_lb;
	      real_ub = old_dtype_ptr->real_ub;
	      }
	  else {
	      if (old_dtype_ptr->real_lb < real_lb) 
		  real_lb = old_dtype_ptr->real_lb;
	      if (old_dtype_ptr->real_ub > real_ub) 
		  real_ub = old_dtype_ptr->real_ub;
	      }
	  /* Next, check to see if datatype has an MPI_LB or MPI_UB
	     within it... 
	     Make sure to adjust the ub by the selected displacement
	     and blocklens (blocklens is like Type_contiguous)
	   */
	  if (old_dtype_ptr->has_ub) {
	      MPI_Aint ub_test;
	      ub_test = old_dtype_ptr->ub + indices[i] + 
		  (blocklens[i] - 1) * old_dtype_ptr->extent;
	      if (ub_marker < ub_test || !ub_found) ub_marker = ub_test;
	      ub_found = 1;
	      }
	  if (old_dtype_ptr->has_lb) {
	      if (!lb_found || lb_marker > (old_dtype_ptr->lb) + indices[i] ) 
		  lb_marker = old_dtype_ptr->lb + indices[i];
	      lb_found  = 1;
	      }
	  /* Get the ub/lb from the datatype (if a MPI_UB or MPI_LB was
	     found, then these values will be ignored). 
	     We use the lb of the old type and add the indices
	     value to it */
	  lb = indices[i] + old_dtype_ptr->lb;
	  ub = lb + (blocklens[i] * old_dtype_ptr->extent) ;
	  if (!high_init) { high = ub; high_init = 1; }
	  else if (ub > high) high = ub;
	  if (!low_init ) { low  = lb; low_init  = 1; }
	  else if (lb < low) low = lb;
	  if (ub > lb) {
	      if ( high < ub ) high = ub;
	      if ( low  > lb ) low  = lb;
	      }
	  else {
	      if ( high < lb ) high = lb;
	      if ( low  > ub ) low  = ub;
	      }
	  dteptr->elements += (blocklens[i] * old_dtype_ptr->elements);
	  } /* end else */
      if (i < count - 1) {
	  size = old_dtype_ptr->size * blocklens[i];
	  dteptr->size   += size; 
      }
      else {
	  dteptr->size     += (blocklens[i] * old_dtype_ptr->size);
      }
      } /* end for loop */
  
  /* Set the upper/lower bounds and the extent and size */
  if (lb_found) {
      dteptr->lb     = lb_marker;
      dteptr->has_lb = 1;
      }
  else 
      dteptr->lb = (low_init  ? low : 0);
  if (ub_found) {
      dteptr->ub     = ub_marker;
      dteptr->has_ub = 1;
      }
  else 
      dteptr->ub = (high_init ? high: 0);
  dteptr->extent      = dteptr->ub - dteptr->lb ;
  dteptr->real_ub     = real_ub;
  dteptr->real_lb     = real_lb;

  /* If there is no explicit ub/lb marker, make the extent/ub fit the
     alignment of the largest basic item, if that structure alignment is
     chosen */

  if (!lb_found && !ub_found) {
      MPI_Aint eps_offset;
      /* Since data is always offset by the extent, is the extent that
	 we must adjust. */
      eps_offset = dteptr->extent % dteptr->align;
      if (eps_offset > 0) {
	  dteptr->ub += (dteptr->align - eps_offset);
	  dteptr->extent = dteptr->ub - dteptr->lb;
      }
  }

# if defined(MPID_HAS_TYPE_STRUCT)
  {
      mpi_errno = MPID_Type_struct(count,
				   blocklens,
				   indices,
				   old_types,
				   *newtype);
  }
# endif      

  revertSignal();
  return (mpi_errno);
}
Ejemplo n.º 5
0
/*@

MPI_Cart_create - Makes a new communicator to which topology information
                  has been attached

Input Parameters:
+ comm_old - input communicator (handle) 
. ndims - number of dimensions of cartesian grid (integer) 
. dims - integer array of size ndims specifying the number of processes in 
  each dimension 
. periods - logical array of size ndims specifying whether the grid is 
  periodic (true) or not (false) in each dimension 
- reorder - ranking may be reordered (true) or not (false) (logical) 

Output Parameter:
. comm_cart - communicator with new cartesian topology (handle) 

Algorithm:
We ignore 'reorder' info currently.

.N fortran

.N Errors
.N MPI_SUCCESS
.N MPI_ERR_TOPOLOGY
.N MPI_ERR_DIMS
.N MPI_ERR_ARG
@*/
int MPI_Cart_create ( MPI_Comm comm_old, int ndims, int *dims, int *periods, 
		      int reorder, MPI_Comm *comm_cart )
{
  int range[1][3];
  MPI_Group group_old, group;
  int i, rank, num_ranks = 1;
  int mpi_errno = MPI_SUCCESS;
  int flag, size;
  MPIR_TOPOLOGY *topo;
  struct MPIR_COMMUNICATOR *comm_old_ptr;
  static char myname[] = "MPI_CART_CREATE";

  TR_PUSH(myname);
  comm_old_ptr = MPIR_GET_COMM_PTR(comm_old);

  /* Check validity of arguments */
#ifndef MPIR_NO_ERROR_CHECKING
  MPIR_TEST_MPI_COMM(comm_old,comm_old_ptr,comm_old_ptr,myname);
  MPIR_TEST_ARG(comm_cart);
  MPIR_TEST_ARG(periods);
  if (ndims < 1 || dims == (int *)0) mpi_errno = MPI_ERR_DIMS;
  if (mpi_errno)
	return MPIR_ERROR(comm_old_ptr, mpi_errno, myname );
  
  /* Check for Intra-communicator */
  MPI_Comm_test_inter ( comm_old, &flag );
  if (flag)
    return MPIR_ERROR(comm_old_ptr, 
            MPIR_ERRCLASS_TO_CODE(MPI_ERR_COMM,MPIR_ERR_COMM_INTER), myname );
#endif

  /* Determine number of ranks in topology */
  for ( i=0; i<ndims; i++ )
    num_ranks    *= (dims[i]>0)?dims[i]:-dims[i];
  if ( num_ranks < 1 ) {
    (*comm_cart)  = MPI_COMM_NULL;
    return MPIR_ERROR( comm_old_ptr, MPI_ERR_TOPOLOGY, myname );
  }

  /* Is the old communicator big enough? */
  MPIR_Comm_size (comm_old_ptr, &size);
  if (num_ranks > size) {
      mpi_errno = MPIR_Err_setmsg( MPI_ERR_TOPOLOGY, MPIR_ERR_TOPO_TOO_LARGE, 
				   myname, 
                  "Topology size is larger than size of communicator",
		  "Topology size %d is greater than communicator size %d", 
				   num_ranks, size );
	return MPIR_ERROR(comm_old_ptr, mpi_errno, myname );
  }
	
  /* Make new comm */
  range[0][0] = 0; range[0][1] = num_ranks - 1; range[0][2] = 1;
  MPI_Comm_group ( comm_old, &group_old );
  MPI_Group_range_incl ( group_old, 1, range, &group );
  MPI_Comm_create  ( comm_old, group, comm_cart );
  MPI_Group_free( &group );
  MPI_Group_free( &group_old );

  /* Store topology information in new communicator */
  if ( (*comm_cart) != MPI_COMM_NULL ) {
      MPIR_ALLOC(topo,(MPIR_TOPOLOGY *) MPIR_SBalloc ( MPIR_topo_els ),
		 comm_old_ptr,MPI_ERR_EXHAUSTED,myname);
      MPIR_SET_COOKIE(&topo->cart,MPIR_CART_TOPOL_COOKIE)
	  topo->cart.type         = MPI_CART;
      topo->cart.nnodes       = num_ranks;
      topo->cart.ndims        = ndims;
      MPIR_ALLOC(topo->cart.dims,(int *)MALLOC( sizeof(int) * 3 * ndims ),
		 comm_old_ptr,MPI_ERR_EXHAUSTED,myname);
      topo->cart.periods      = topo->cart.dims + ndims;
      topo->cart.position     = topo->cart.periods + ndims;
      for ( i=0; i<ndims; i++ ) {
	  topo->cart.dims[i]    = dims[i];
	  topo->cart.periods[i] = periods[i];
      }

    /* Compute my position */
    MPI_Comm_rank ( (*comm_cart), &rank );
    for ( i=0; i < ndims; i++ ) {
      num_ranks = num_ranks / dims[i];
      topo->cart.position[i]  = rank / num_ranks;
      rank   = rank % num_ranks;
    }

    /* cache topology information */
    MPI_Attr_put ( (*comm_cart), MPIR_TOPOLOGY_KEYVAL, (void *)topo );
  }
  TR_POP;
  return (mpi_errno);
}
Ejemplo n.º 6
0
/*@

MPI_Group_range_excl - Produces a group by excluding ranges of processes from
       an existing group

Input Parameters:
+ group - group (handle) 
. n - number of elements in array 'ranks' (integer) 
- ranges - a one-dimensional 
array of integer triplets of the
form (first rank, last rank, stride), indicating the ranks in
'group'  of processes to be excluded
from the output group 'newgroup' .  

Output Parameter:
. newgroup - new group derived from above, preserving the 
order in 'group'  (handle) 

Note:  
Currently, each of the ranks to exclude must be
a valid rank in the group and all elements must be distinct or the
function is erroneous.  This restriction is per the draft.

.N fortran

.N Errors
.N MPI_SUCCESS
.N MPI_ERR_GROUP
.N MPI_ERR_EXHAUSTED
.N MPI_ERR_RANK
.N MPI_ERR_ARG

.seealso: MPI_Group_free
@*/
EXPORT_MPI_API int MPI_Group_range_excl ( MPI_Group group, int n, int ranges[][3], 
			   MPI_Group *newgroup )
{
  int i, j, first, last, stride;
  int np;
  struct MPIR_GROUP *group_ptr, *new_group_ptr;
  int mpi_errno = MPI_SUCCESS;
  static char myname[] = "MPI_GROUP_RANGE_EXCL";

  TR_PUSH(myname);

  /* Check for bad arguments */
  group_ptr = MPIR_GET_GROUP_PTR(group);
#ifndef MPIR_NO_ERROR_CHECKING
  /* MPIR_TEST_MPI_GROUP(group,group_ptr,MPIR_COMM_WORLD,myname); */
  MPIR_TEST_GROUP(group_ptr);
    if (mpi_errno)
	return MPIR_ERROR(MPIR_COMM_WORLD, mpi_errno, myname );
#endif

  /* Check for a EMPTY input group */
  if ( (group == MPI_GROUP_EMPTY) ) {
      MPIR_Group_dup ( MPIR_GROUP_EMPTY, &new_group_ptr );
      *newgroup = new_group_ptr->self;
      TR_POP;
      return (mpi_errno);
  }

  /* Check for no range ranks to exclude */
  if ( n == 0 ) {
    MPIR_Group_dup ( group_ptr, &new_group_ptr );
    *newgroup = new_group_ptr->self;
    return (mpi_errno);
  }

  if (n < 0) 
      return MPIR_ERROR( MPIR_COMM_WORLD, MPI_ERR_ARG, myname );

  /* Allocate set marking space for group if necessary */
  if (group_ptr->set_mark == NULL) {
      MPIR_ALLOC(group_ptr->set_mark,(int *) MALLOC( group_ptr->np * sizeof(int) ),
		 MPIR_COMM_WORLD, MPI_ERR_EXHAUSTED, myname );
  }
  (void) memset( group_ptr->set_mark, (char)0, group_ptr->np * sizeof(int) );

  /* Mark the ranks to be excluded */
  np = group_ptr->np;  
  for (i=0; i<n; i++) {
    first = ranges[i][0]; last = ranges[i][1]; stride = ranges[i][2];
    if (stride != 0) {
	if ( (stride > 0 && first > last) ||
	     (stride < 0 && first < last) ) {
	    mpi_errno = MPIR_Err_setmsg( MPI_ERR_ARG, MPIR_ERR_ARG_STRIDE,
					 myname, 
		 "Range does not terminate", 
		 "Range (%d,%d,%d) does not terminate", first, last, stride );
	    return MPIR_ERROR( MPIR_COMM_WORLD, mpi_errno, myname );
	}
	for ( j=first; j*stride <= last*stride; j += stride )
	  if ( (j < group_ptr->np) && (j >= 0) ) {
	      if (group_ptr->set_mark[j] == MPIR_UNMARKED) {
		  group_ptr->set_mark[j] = MPIR_MARKED;
		  np--;
	      }
	  }
	  else{
	      mpi_errno = MPIR_Err_setmsg( MPI_ERR_RANK, MPIR_ERR_DEFAULT, 
					   myname, (char *)0,(char *)0, j );
	      return MPIR_ERROR( MPIR_COMM_WORLD, mpi_errno, myname );
	  }
    }
    else {
	mpi_errno = MPIR_Err_setmsg( MPI_ERR_ARG, MPIR_ERR_ARG_ZERO_STRIDE, 
				     myname, "Zero stride is incorrect",
				     (char *)0 );
	return MPIR_ERROR( MPIR_COMM_WORLD, mpi_errno, myname );
    }
  }

  /* Check np to see if we have original group or if we have null group */
  if (np == 0) {
      MPIR_Group_dup ( MPIR_GROUP_EMPTY, &new_group_ptr );
      *newgroup = new_group_ptr->self;
      return (mpi_errno);
  }
  if (np == group_ptr->np) {
    MPIR_Group_dup ( group_ptr, &new_group_ptr );
    *newgroup = new_group_ptr->self;
    return (mpi_errno);
  }

  /* Create the new group */
  MPIR_ALLOC(new_group_ptr,NEW(struct MPIR_GROUP),MPIR_COMM_WORLD, 
	     MPI_ERR_EXHAUSTED, myname );
  *newgroup = (MPI_Group) MPIR_FromPointer( new_group_ptr );
  new_group_ptr->self = *newgroup;
  MPIR_SET_COOKIE(new_group_ptr,MPIR_GROUP_COOKIE)
  new_group_ptr->ref_count      = 1;
  new_group_ptr->permanent      = 0;
  new_group_ptr->local_rank     = MPI_UNDEFINED;
  new_group_ptr->set_mark       = (int *)0;
  new_group_ptr->np             = np;
  new_group_ptr->lrank_to_grank = (int *) MALLOC( np * sizeof(int) );
  if (!new_group_ptr->lrank_to_grank) {
	return MPIR_ERROR( MPIR_COMM_WORLD, MPI_ERR_EXHAUSTED, myname );
  }
  
  /* Fill in new group */
  for (i=j=0; i < group_ptr->np ; i++) 
    if ( (group_ptr->set_mark[i] == MPIR_UNMARKED) && (j < new_group_ptr->np ) ) {
      if (group_ptr->local_rank == i)
        new_group_ptr->local_rank = j;
      new_group_ptr->lrank_to_grank[j++] = group_ptr->lrank_to_grank[i];
    }

  /* Determine the previous and next powers of 2 */
  MPIR_Powers_of_2 ( new_group_ptr->np, &(new_group_ptr->N2_next), 
		     &(new_group_ptr->N2_prev) );

  TR_POP;
  return (mpi_errno);
}