99144db970
Some MPI C interface files saw some spacing changes to conform to the coding standards of Open MPI. Changed MPI C interface files to use {{{OPAL_CR_ENTER_LIBRARY()}}} and {{{OPAL_CR_EXIT_LIBRARY()}}} instead of just {{{OPAL_CR_TEST_CHECKPOINT_READY()}}}. This will allow the checkpoint/restart system more flexibility in how it is to behave. Fixed the configure check for {{{--enable-ft-thread}}} so it has a know dependance on {{{--enable-mpi-thread}}} (and/or {{{--enable-progress-thread}}}). Added a line for Checkpoint/Restart support to {{{ompi_info}}}. Added some options to choose at runtime whether or not to use the checkpoint polling thread. By default, if the user asked for it to be compiled in, then it is used. But some users will want the ability to toggle its use at runtime. There are still some places for improvement, but the feature works correctly. As always with Checkpoint/Restart, it is compiled out unless explicitly asked for at configure time. Further, if it was configured in, then it is not used unless explicitly asked for by the user at runtime. This commit was SVN r17516.
308 строки
7.6 KiB
C
308 строки
7.6 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$
|
|
*
|
|
* Additional copyrights may follow
|
|
*
|
|
* $HEADER$
|
|
*/
|
|
|
|
#include "ompi_config.h"
|
|
|
|
#include "ompi/mpi/c/bindings.h"
|
|
|
|
#if OMPI_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);
|
|
}
|
|
}
|
|
|
|
/* 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) {
|
|
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_DIMS,
|
|
FUNC_NAME);
|
|
}
|
|
else 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;
|
|
}
|
|
|