1
1
openmpi/ompi/mpi/c/dims_create.c
Christoph Niethammer 85dce869c8 Move parameter check into appropriate code section at the begin.
Freeprocs variable was obtained from nnodes, so check the value of nnodes at
the begin in the MPI_PARAM_CHECK code section instead as discussed at the
developer list.

cmr=v1.7.5:reviewer=jsquyres:subject=move parameter check to begin


jsquyres, please review this CMR. Thanks.

This commit was SVN r30694.
2014-02-12 08:30:13 +00:00

313 строки
7.8 KiB
C

/*
* Copyright (c) 2004-2007 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 (c) 2012 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/communicator/communicator.h"
#include "ompi/errhandler/errhandler.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Dims_create = PMPI_Dims_create
#endif
#if OMPI_PROFILING_DEFINES
#include "ompi/mpi/c/profile/defines.h"
#endif
static const char FUNC_NAME[] = "MPI_Dims_create";
/* static functions */
static int assignnodes(int ndim, int nfactor, int *pfacts, int *counts, int **pdims);
static int getfactors(int num, int nprime, int *primes, int **pcounts);
static int getprimes(int num, int *pnprime, int **pprimes);
/*
* This is a utility function, no need to have anything in the lower
* layer for this at all
*/
int MPI_Dims_create(int nnodes, int ndims, int dims[])
{
int i;
int freeprocs;
int freedims;
int nprimes;
int *primes;
int *factors;
int *procs;
int *p;
int err;
OPAL_CR_NOOP_PROGRESS();
if (MPI_PARAM_CHECK) {
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
if (NULL == dims) {
return OMPI_ERRHANDLER_INVOKE (MPI_COMM_WORLD,
MPI_ERR_ARG, FUNC_NAME);
}
if (1 > ndims) {
return OMPI_ERRHANDLER_INVOKE (MPI_COMM_WORLD,
MPI_ERR_DIMS, FUNC_NAME);
}
if (1 > nnodes) {
return OMPI_ERRHANDLER_INVOKE (MPI_COMM_WORLD,
MPI_ERR_DIMS, FUNC_NAME);
}
}
/* Get # of free-to-be-assigned processes and # of free dimensions */
freeprocs = nnodes;
freedims = 0;
for (i = 0, p = dims; i < ndims; ++i,++p) {
if (*p == 0) {
++freedims;
} else if ((*p < 0) || ((nnodes % *p) != 0)) {
return OMPI_ERRHANDLER_INVOKE (MPI_COMM_WORLD, MPI_ERR_DIMS,
FUNC_NAME);
} else {
freeprocs /= *p;
}
}
if (freedims == 0) {
if (freeprocs == 1) {
return MPI_SUCCESS;
}
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_DIMS,
FUNC_NAME);
}
if (freeprocs == 1) {
for (i = 0; i < ndims; ++i, ++dims) {
if (*dims == 0) {
*dims = 1;
}
}
return MPI_SUCCESS;
}
/* Compute the relevant prime numbers for factoring */
if (MPI_SUCCESS != (err = getprimes(freeprocs, &nprimes, &primes))) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, err,
FUNC_NAME);
}
/* Factor the number of free processes */
if (MPI_SUCCESS != (err = getfactors(freeprocs, nprimes, primes, &factors))) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, err,
FUNC_NAME);
}
/* Assign free processes to free dimensions */
if (MPI_SUCCESS != (err = assignnodes(freedims, nprimes, primes, factors, &procs))) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, err,
FUNC_NAME);
}
/* Return assignment results */
p = procs;
for (i = 0; i < ndims; ++i, ++dims) {
if (*dims == 0) {
*dims = *p++;
}
}
free((char *) primes);
free((char *) factors);
free((char *) procs);
/* all done */
return MPI_SUCCESS;
}
/*
* assignnodes
*
* Function: - assign processes to dimensions
* - get "best-balanced" grid
* - greedy bin-packing algorithm used
* - sort dimensions in decreasing order
* - dimensions array dynamically allocated
* Accepts: - # of dimensions
* - # of prime factors
* - array of prime factors
* - array of factor counts
* - ptr to array of dimensions (returned value)
* Returns: - 0 or ERROR
*/
static int
assignnodes(int ndim, int nfactor, int *pfacts, int *counts, int **pdims)
{
int *bins;
int i, j;
int n;
int f;
int *p;
int *pmin;
if (0 >= ndim) {
return MPI_ERR_DIMS;
}
/* Allocate and initialize the bins */
bins = (int *) malloc((unsigned) ndim * sizeof(int));
if (NULL == bins) {
return MPI_ERR_NO_MEM;
}
*pdims = bins;
for (i = 0, p = bins; i < ndim; ++i, ++p) {
*p = 1;
}
/* Loop assigning factors from the highest to the lowest */
for (j = nfactor - 1; j >= 0; --j) {
f = pfacts[j];
for (n = counts[j]; n > 0; --n) {
/* Assign a factor to the smallest bin */
pmin = bins;
for (i = 1, p = pmin + 1; i < ndim; ++i, ++p) {
if (*p < *pmin) {
pmin = p;
}
}
*pmin *= f;
}
}
/* Sort dimensions in decreasing order (O(n^2) for now) */
for (i = 0, pmin = bins; i < ndim - 1; ++i, ++pmin) {
for (j = i + 1, p = pmin + 1; j < ndim; ++j, ++p) {
if (*p > *pmin) {
n = *p;
*p = *pmin;
*pmin = n;
}
}
}
return MPI_SUCCESS;
}
/*
* getfactors
*
* Function: - factorize a number
* Accepts: - number
* - # of primes
* - array of primes
* - ptr to array of counts (returned value)
* Returns: - 0 or ERROR
*/
static int
getfactors(int num, int nprime, int *primes, int **pcounts)
{
int *counts;
int i;
int *p;
int *c;
if (0 >= nprime) {
return MPI_ERR_INTERN;
}
/* Allocate the factor counts array */
counts = (int *) malloc((unsigned) nprime * sizeof(int));
if (NULL == counts) {
return MPI_ERR_NO_MEM;
}
*pcounts = counts;
/* Loop over the prime numbers */
i = nprime - 1;
p = primes + i;
c = counts + i;
for (; i >= 0; --i, --p, --c) {
*c = 0;
while ((num % *p) == 0) {
++(*c);
num /= *p;
}
}
if (1 != num) {
return MPI_ERR_INTERN;
}
return MPI_SUCCESS;
}
/*
* getprimes
*
* Function: - get primes smaller than number
* - array of primes dynamically allocated
* Accepts: - number
* - ptr # of primes (returned value)
* - ptr array of primes (returned values)
* Returns: - 0 or ERROR
*/
static int
getprimes(int num, int *pnprime, int **pprimes) {
int i, j;
int n;
int size;
int *primes;
/* Allocate the array of primes */
size = (num / 2) + 1;
primes = (int *) malloc((unsigned) size * sizeof(int));
if (NULL == primes) {
return MPI_ERR_NO_MEM;
}
*pprimes = primes;
/* Find the prime numbers */
i = 0;
primes[i++] = 2;
for (n = 3; n <= num; n += 2) {
for (j = 1; j < i; ++j) {
if ((n % primes[j]) == 0) {
break;
}
}
if (j == i) {
if (i >= size) {
return MPI_ERR_DIMS;
}
primes[i++] = n;
}
}
*pnprime = i;
return MPI_SUCCESS;
}