/* * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. * Copyright (c) 2004-2005 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ #include "ompi_config.h" #include "mca/topo/base/base.h" #include "communicator/communicator.h" #include "mca/topo/topo.h" /* * function - partitions a communicator into subgroups which * form lower-dimensional cartesian subgrids * * @param comm communicator with cartesian structure (handle) * @param remain_dims the 'i'th entry of 'remain_dims' specifies whether * the 'i'th dimension is kept in the subgrid (true) * or is dropped (false) (logical vector) * @param new_comm communicator containing the subgrid that includes the * calling process (handle) * * @retval MPI_SUCCESS * @retval MPI_ERR_TOPOLOGY * @retval MPI_ERR_COMM */ int mca_topo_base_cart_sub (MPI_Comm comm, int *remain_dims, MPI_Comm *new_comm){ struct ompi_communicator_t *temp_comm; int errcode; int colour; int key; int colfactor; int keyfactor; int rank; int ndim; int dim; bool allfalse; int i; int *d; int *c; int *r; int *p; *new_comm = MPI_COMM_NULL; /* * Compute colour and key used in splitting the communicator. */ colour = key = 0; colfactor = keyfactor = 1; ndim = 0; allfalse = false; i = comm->c_topo_comm->mtc_ndims_or_nnodes - 1; d = comm->c_topo_comm->mtc_dims_or_index + i; c = comm->c_topo_comm->mtc_coords + i; r = remain_dims + i; for (; i >= 0; --i, --d, --c, --r) { dim = (*d > 0) ? *d : -(*d); if (*r == 0) { colour += colfactor * (*c); colfactor *= dim; } else { ++ndim; key += keyfactor * (*c); keyfactor *= dim; } } /* * Special case: if all of remain_dims were false, we need to make * a cartesian communicator with just ourselves in it (you can't * have a communicator unless you're in it). */ if (ndim == 0) { colour = ompi_comm_rank (comm); ndim = 1; allfalse = true; } /* * Split the communicator. */ errcode = ompi_comm_split (comm, colour, key, &temp_comm, true); if (errcode != MPI_SUCCESS) { return errcode; } /* * Fill the communicator with topology information. */ if (temp_comm != MPI_COMM_NULL) { temp_comm->c_topo_comm->mtc_ndims_or_nnodes = ndim; if (!allfalse) { p = temp_comm->c_topo_comm->mtc_dims_or_index; d = comm->c_topo_comm->mtc_dims_or_index; r = remain_dims; for (i = 0; i < comm->c_topo_comm->mtc_ndims_or_nnodes; ++i, ++d, ++r) { if (*r) { *p++ = *d; } } } else { temp_comm->c_topo_comm->mtc_dims_or_index[0] = 1; } /* * Compute the caller's coordinates. */ rank = ompi_comm_rank (temp_comm); if (MPI_SUCCESS != errcode) { OBJ_RELEASE(temp_comm); return errcode; } errcode = temp_comm->c_topo->topo_cart_coords (temp_comm, rank, ndim, temp_comm->c_topo_comm->mtc_coords); if (MPI_SUCCESS != errcode) { OBJ_RELEASE(temp_comm); return errcode; } } *new_comm = temp_comm; return MPI_SUCCESS; }