|
Packit Service |
c5cf8c |
/* -*- Mode: C++; c-basic-offset:4 ; -*- */
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* (C) 2001 by Argonne National Laboratory.
|
|
Packit Service |
c5cf8c |
* See COPYRIGHT in top-level directory.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
#include "mpi.h"
|
|
Packit Service |
c5cf8c |
#include "mpitestconf.h"
|
|
Packit Service |
c5cf8c |
#ifdef HAVE_IOSTREAM
|
|
Packit Service |
c5cf8c |
// Not all C++ compilers have iostream instead of iostream.h
|
|
Packit Service |
c5cf8c |
#include <iostream>
|
|
Packit Service |
c5cf8c |
#ifdef HAVE_NAMESPACE_STD
|
|
Packit Service |
c5cf8c |
// Those that do often need the std namespace; otherwise, a bare "cout"
|
|
Packit Service |
c5cf8c |
// is likely to fail to compile
|
|
Packit Service |
c5cf8c |
using namespace std;
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
#else
|
|
Packit Service |
c5cf8c |
#include <iostream.h>
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
#include "mpitestcxx.h"
|
|
Packit Service |
c5cf8c |
#include <stdlib.h>
|
|
Packit Service |
c5cf8c |
#include <string.h>
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int dbgflag = 0; /* Flag used for debugging */
|
|
Packit Service |
c5cf8c |
static int wrank = -1; /* World rank */
|
|
Packit Service |
c5cf8c |
static int verbose = 0; /* Message level (0 is none) */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void MTestRMACleanup(void);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Initialize and Finalize MTest
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
Initialize MTest, initializing MPI if necessary.
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
Environment Variables:
|
|
Packit Service |
c5cf8c |
+ MPITEST_DEBUG - If set (to any value), turns on debugging output
|
|
Packit Service |
c5cf8c |
- MPITEST_VERBOSE - If set to a numeric value, turns on that level of
|
|
Packit Service |
c5cf8c |
verbose output.
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
void MTest_Init(void)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
bool flag;
|
|
Packit Service |
c5cf8c |
const char *envval = 0;
|
|
Packit Service |
c5cf8c |
int threadLevel, provided;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
threadLevel = MPI::THREAD_SINGLE;
|
|
Packit Service |
c5cf8c |
envval = getenv("MTEST_THREADLEVEL_DEFAULT");
|
|
Packit Service |
c5cf8c |
if (envval && *envval) {
|
|
Packit Service |
c5cf8c |
if (strcmp(envval, "MULTIPLE") == 0 || strcmp(envval, "multiple") == 0) {
|
|
Packit Service |
c5cf8c |
threadLevel = MPI::THREAD_MULTIPLE;
|
|
Packit Service |
c5cf8c |
} else if (strcmp(envval, "SERIALIZED") == 0 || strcmp(envval, "serialized") == 0) {
|
|
Packit Service |
c5cf8c |
threadLevel = MPI::THREAD_SERIALIZED;
|
|
Packit Service |
c5cf8c |
} else if (strcmp(envval, "FUNNELED") == 0 || strcmp(envval, "funneled") == 0) {
|
|
Packit Service |
c5cf8c |
threadLevel = MPI::THREAD_FUNNELED;
|
|
Packit Service |
c5cf8c |
} else if (strcmp(envval, "SINGLE") == 0 || strcmp(envval, "single") == 0) {
|
|
Packit Service |
c5cf8c |
threadLevel = MPI::THREAD_SINGLE;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
cerr << "Unrecognized thread level " << envval << "\n";
|
|
Packit Service |
c5cf8c |
cerr.flush();
|
|
Packit Service |
c5cf8c |
/* Use exit since MPI_Init/Init_thread has not been called. */
|
|
Packit Service |
c5cf8c |
exit(1);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
flag = MPI::Is_initialized();
|
|
Packit Service |
c5cf8c |
if (!flag) {
|
|
Packit Service |
c5cf8c |
provided = MPI::Init_thread(threadLevel);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#if defined(HAVE_MPI_IO)
|
|
Packit Service |
c5cf8c |
MPI::FILE_NULL.Set_errhandler(MPI::ERRORS_THROW_EXCEPTIONS);
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Check for debugging control */
|
|
Packit Service |
c5cf8c |
if (getenv("MPITEST_DEBUG")) {
|
|
Packit Service |
c5cf8c |
dbgflag = 1;
|
|
Packit Service |
c5cf8c |
wrank = MPI::COMM_WORLD.Get_rank();
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Check for verbose control */
|
|
Packit Service |
c5cf8c |
envval = getenv("MPITEST_VERBOSE");
|
|
Packit Service |
c5cf8c |
if (envval) {
|
|
Packit Service |
c5cf8c |
char *s;
|
|
Packit Service |
c5cf8c |
long val = strtol(envval, &s, 0);
|
|
Packit Service |
c5cf8c |
if (s == envval) {
|
|
Packit Service |
c5cf8c |
/* This is the error case for strtol */
|
|
Packit Service |
c5cf8c |
cerr << "Warning: " << envval << " not valid for MPITEST_VERBOSE\n";
|
|
Packit Service |
c5cf8c |
cerr.flush();
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
if (val >= 0) {
|
|
Packit Service |
c5cf8c |
verbose = val;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
cerr << "Warning: " << envval << " not valid for MPITEST_VERBOSE\n";
|
|
Packit Service |
c5cf8c |
cerr.flush();
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
Finalize MTest. errs is the number of errors on the calling process;
|
|
Packit Service |
c5cf8c |
this routine will write the total number of errors over all of MPI_COMM_WORLD
|
|
Packit Service |
c5cf8c |
to the process with rank zero, or " No Errors".
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
void MTest_Finalize(int errs)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int rank, toterrs;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
rank = MPI::COMM_WORLD.Get_rank();
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPI::COMM_WORLD.Allreduce(&errs, &toterrs, 1, MPI::INT, MPI::SUM);
|
|
Packit Service |
c5cf8c |
if (rank == 0) {
|
|
Packit Service |
c5cf8c |
if (toterrs) {
|
|
Packit Service |
c5cf8c |
cout << " Found " << toterrs << " errors\n";
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
cout << " No Errors\n";
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
cout.flush();
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
// Clean up any persistent objects that we allocated
|
|
Packit Service |
c5cf8c |
MTestRMACleanup();
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPI::Finalize();
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* ----------------------------------------------------------------------- */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Create communicators. Use separate routines for inter and intra
|
|
Packit Service |
c5cf8c |
* communicators (there is a routine to give both)
|
|
Packit Service |
c5cf8c |
* Note that the routines may return MPI::COMM_NULL, so code should test for
|
|
Packit Service |
c5cf8c |
* that return value as well.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
static int interCommIdx = 0;
|
|
Packit Service |
c5cf8c |
static int intraCommIdx = 0;
|
|
Packit Service |
c5cf8c |
static const char *intraCommName = 0;
|
|
Packit Service |
c5cf8c |
static const char *interCommName = 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Get an intracommunicator with at least min_size members. If "allowSmaller"
|
|
Packit Service |
c5cf8c |
* is true, allow the communicator to be smaller than MPI::COMM_WORLD and
|
|
Packit Service |
c5cf8c |
* for this routine to return MPI::COMM_NULL for some values. Returns 0 if
|
|
Packit Service |
c5cf8c |
* no more communicators are available.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
int MTestGetIntracommGeneral(MPI::Intracomm & comm, int min_size, bool allowSmaller)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int size, rank;
|
|
Packit Service |
c5cf8c |
bool done = false;
|
|
Packit Service |
c5cf8c |
bool isBasic = false;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* The while loop allows us to skip communicators that are too small.
|
|
Packit Service |
c5cf8c |
* MPI::COMM_NULL is always considered large enough */
|
|
Packit Service |
c5cf8c |
while (!done) {
|
|
Packit Service |
c5cf8c |
switch (intraCommIdx) {
|
|
Packit Service |
c5cf8c |
case 0:
|
|
Packit Service |
c5cf8c |
comm = MPI::COMM_WORLD;
|
|
Packit Service |
c5cf8c |
isBasic = true;
|
|
Packit Service |
c5cf8c |
intraCommName = "MPI::COMM_WORLD";
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case 1:
|
|
Packit Service |
c5cf8c |
/* dup of world */
|
|
Packit Service |
c5cf8c |
comm = MPI::COMM_WORLD.Dup();
|
|
Packit Service |
c5cf8c |
intraCommName = "Dup of MPI::COMM_WORLD";
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case 2:
|
|
Packit Service |
c5cf8c |
/* reverse ranks */
|
|
Packit Service |
c5cf8c |
size = MPI::COMM_WORLD.Get_size();
|
|
Packit Service |
c5cf8c |
rank = MPI::COMM_WORLD.Get_rank();
|
|
Packit Service |
c5cf8c |
comm = MPI::COMM_WORLD.Split(0, size - rank);
|
|
Packit Service |
c5cf8c |
intraCommName = "Rank reverse of MPI::COMM_WORLD";
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case 3:
|
|
Packit Service |
c5cf8c |
/* subset of world, with reversed ranks */
|
|
Packit Service |
c5cf8c |
size = MPI::COMM_WORLD.Get_size();
|
|
Packit Service |
c5cf8c |
rank = MPI::COMM_WORLD.Get_rank();
|
|
Packit Service |
c5cf8c |
comm = MPI::COMM_WORLD.Split((rank < size / 2), size - rank);
|
|
Packit Service |
c5cf8c |
intraCommName = "Rank reverse of half of MPI::COMM_WORLD";
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case 4:
|
|
Packit Service |
c5cf8c |
comm = MPI::COMM_SELF;
|
|
Packit Service |
c5cf8c |
isBasic = true;
|
|
Packit Service |
c5cf8c |
intraCommName = "MPI::COMM_SELF";
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* These next cases are communicators that include some
|
|
Packit Service |
c5cf8c |
* but not all of the processes */
|
|
Packit Service |
c5cf8c |
case 5:
|
|
Packit Service |
c5cf8c |
case 6:
|
|
Packit Service |
c5cf8c |
case 7:
|
|
Packit Service |
c5cf8c |
case 8:
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int newsize;
|
|
Packit Service |
c5cf8c |
size = MPI::COMM_WORLD.Get_size();
|
|
Packit Service |
c5cf8c |
newsize = size - (intraCommIdx - 4);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (allowSmaller && newsize >= min_size) {
|
|
Packit Service |
c5cf8c |
rank = MPI::COMM_WORLD.Get_rank();
|
|
Packit Service |
c5cf8c |
comm = MPI::COMM_WORLD.Split(rank < newsize, rank);
|
|
Packit Service |
c5cf8c |
if (rank >= newsize) {
|
|
Packit Service |
c5cf8c |
comm.Free();
|
|
Packit Service |
c5cf8c |
comm = MPI::COMM_NULL;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
/* Act like default */
|
|
Packit Service |
c5cf8c |
comm = MPI::COMM_NULL;
|
|
Packit Service |
c5cf8c |
isBasic = true;
|
|
Packit Service |
c5cf8c |
intraCommName = "MPI::COMM_NULL";
|
|
Packit Service |
c5cf8c |
intraCommIdx = -1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Other ideas: dup of self, cart comm, graph comm */
|
|
Packit Service |
c5cf8c |
default:
|
|
Packit Service |
c5cf8c |
comm = MPI::COMM_NULL;
|
|
Packit Service |
c5cf8c |
isBasic = true;
|
|
Packit Service |
c5cf8c |
intraCommName = "MPI::COMM_NULL";
|
|
Packit Service |
c5cf8c |
intraCommIdx = -1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (comm != MPI::COMM_NULL) {
|
|
Packit Service |
c5cf8c |
size = comm.Get_size();
|
|
Packit Service |
c5cf8c |
if (size >= min_size)
|
|
Packit Service |
c5cf8c |
done = true;
|
|
Packit Service |
c5cf8c |
else {
|
|
Packit Service |
c5cf8c |
/* Try again */
|
|
Packit Service |
c5cf8c |
if (!isBasic)
|
|
Packit Service |
c5cf8c |
comm.Free();
|
|
Packit Service |
c5cf8c |
intraCommIdx++;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else
|
|
Packit Service |
c5cf8c |
done = true;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
intraCommIdx++;
|
|
Packit Service |
c5cf8c |
return intraCommIdx;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Get an intracommunicator with at least min_size members.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
int MTestGetIntracomm(MPI::Intracomm & comm, int min_size)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
return MTestGetIntracommGeneral(comm, min_size, false);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Return the name of an intra communicator */
|
|
Packit Service |
c5cf8c |
const char *MTestGetIntracommName(void)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
return intraCommName;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Return an intercomm; set isLeftGroup to 1 if the calling process is
|
|
Packit Service |
c5cf8c |
* a member of the "left" group.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
int MTestGetIntercomm(MPI::Intercomm & comm, int &isLeftGroup, int min_size)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int size, rank, remsize;
|
|
Packit Service |
c5cf8c |
bool done = false;
|
|
Packit Service |
c5cf8c |
MPI::Intracomm mcomm;
|
|
Packit Service |
c5cf8c |
int rleader;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* The while loop allows us to skip communicators that are too small.
|
|
Packit Service |
c5cf8c |
* MPI::COMM_NULL is always considered large enough. The size is
|
|
Packit Service |
c5cf8c |
* the sum of the sizes of the local and remote groups */
|
|
Packit Service |
c5cf8c |
while (!done) {
|
|
Packit Service |
c5cf8c |
comm = MPI::COMM_NULL;
|
|
Packit Service |
c5cf8c |
isLeftGroup = 0;
|
|
Packit Service |
c5cf8c |
interCommName = "MPI_COMM_NULL";
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
switch (interCommIdx) {
|
|
Packit Service |
c5cf8c |
case 0:
|
|
Packit Service |
c5cf8c |
/* Split comm world in half */
|
|
Packit Service |
c5cf8c |
rank = MPI::COMM_WORLD.Get_rank();
|
|
Packit Service |
c5cf8c |
size = MPI::COMM_WORLD.Get_size();
|
|
Packit Service |
c5cf8c |
if (size > 1) {
|
|
Packit Service |
c5cf8c |
mcomm = MPI::COMM_WORLD.Split((rank < size / 2), rank);
|
|
Packit Service |
c5cf8c |
if (rank == 0) {
|
|
Packit Service |
c5cf8c |
rleader = size / 2;
|
|
Packit Service |
c5cf8c |
} else if (rank == size / 2) {
|
|
Packit Service |
c5cf8c |
rleader = 0;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
/* Remote leader is signficant only for the processes
|
|
Packit Service |
c5cf8c |
* designated local leaders */
|
|
Packit Service |
c5cf8c |
rleader = -1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
isLeftGroup = rank < size / 2;
|
|
Packit Service |
c5cf8c |
comm = mcomm.Create_intercomm(0, MPI::COMM_WORLD, rleader, 12345);
|
|
Packit Service |
c5cf8c |
mcomm.Free();
|
|
Packit Service |
c5cf8c |
interCommName = "Intercomm by splitting MPI::COMM_WORLD";
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
comm = MPI::COMM_NULL;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case 1:
|
|
Packit Service |
c5cf8c |
/* Split comm world in to 1 and the rest */
|
|
Packit Service |
c5cf8c |
rank = MPI::COMM_WORLD.Get_rank();
|
|
Packit Service |
c5cf8c |
size = MPI::COMM_WORLD.Get_size();
|
|
Packit Service |
c5cf8c |
if (size > 1) {
|
|
Packit Service |
c5cf8c |
mcomm = MPI::COMM_WORLD.Split(rank == 0, rank);
|
|
Packit Service |
c5cf8c |
if (rank == 0) {
|
|
Packit Service |
c5cf8c |
rleader = 1;
|
|
Packit Service |
c5cf8c |
} else if (rank == 1) {
|
|
Packit Service |
c5cf8c |
rleader = 0;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
/* Remote leader is signficant only for the processes
|
|
Packit Service |
c5cf8c |
* designated local leaders */
|
|
Packit Service |
c5cf8c |
rleader = -1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
isLeftGroup = rank == 0;
|
|
Packit Service |
c5cf8c |
comm = mcomm.Create_intercomm(0, MPI::COMM_WORLD, rleader, 12346);
|
|
Packit Service |
c5cf8c |
mcomm.Free();
|
|
Packit Service |
c5cf8c |
interCommName = "Intercomm by splitting MPI::COMM_WORLD into 1, rest";
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
comm = MPI::COMM_NULL;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
case 2:
|
|
Packit Service |
c5cf8c |
/* Split comm world in to 2 and the rest */
|
|
Packit Service |
c5cf8c |
rank = MPI::COMM_WORLD.Get_rank();
|
|
Packit Service |
c5cf8c |
size = MPI::COMM_WORLD.Get_size();
|
|
Packit Service |
c5cf8c |
if (size > 3) {
|
|
Packit Service |
c5cf8c |
mcomm = MPI::COMM_WORLD.Split(rank < 2, rank);
|
|
Packit Service |
c5cf8c |
if (rank == 0) {
|
|
Packit Service |
c5cf8c |
rleader = 2;
|
|
Packit Service |
c5cf8c |
} else if (rank == 2) {
|
|
Packit Service |
c5cf8c |
rleader = 0;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
/* Remote leader is signficant only for the processes
|
|
Packit Service |
c5cf8c |
* designated local leaders */
|
|
Packit Service |
c5cf8c |
rleader = -1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
isLeftGroup = rank < 2;
|
|
Packit Service |
c5cf8c |
comm = mcomm.Create_intercomm(0, MPI::COMM_WORLD, rleader, 12347);
|
|
Packit Service |
c5cf8c |
mcomm.Free();
|
|
Packit Service |
c5cf8c |
interCommName = "Intercomm by splitting MPI::COMM_WORLD into 2, rest";
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
comm = MPI::COMM_NULL;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
default:
|
|
Packit Service |
c5cf8c |
comm = MPI::COMM_NULL;
|
|
Packit Service |
c5cf8c |
interCommName = "MPI::COMM_NULL";
|
|
Packit Service |
c5cf8c |
interCommIdx = -1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (comm != MPI::COMM_NULL) {
|
|
Packit Service |
c5cf8c |
size = comm.Get_size();
|
|
Packit Service |
c5cf8c |
remsize = comm.Get_remote_size();
|
|
Packit Service |
c5cf8c |
if (size + remsize >= min_size)
|
|
Packit Service |
c5cf8c |
done = true;
|
|
Packit Service |
c5cf8c |
} else
|
|
Packit Service |
c5cf8c |
done = true;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* we are only done if all processes are done */
|
|
Packit Service |
c5cf8c |
MPI::COMM_WORLD.Allreduce(MPI_IN_PLACE, &done, 1, MPI::BOOL, MPI::LAND);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Advance the comm index whether we are done or not, otherwise we could
|
|
Packit Service |
c5cf8c |
* spin forever trying to allocate a too-small communicator over and
|
|
Packit Service |
c5cf8c |
* over again. */
|
|
Packit Service |
c5cf8c |
interCommIdx++;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!done && comm != MPI::COMM_NULL) {
|
|
Packit Service |
c5cf8c |
comm.Free();
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return interCommIdx;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Return the name of an intercommunicator */
|
|
Packit Service |
c5cf8c |
const char *MTestGetIntercommName(void)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
return interCommName;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Get a communicator of a given minimum size. Both intra and inter
|
|
Packit Service |
c5cf8c |
communicators are provided
|
|
Packit Service |
c5cf8c |
Because Comm is an abstract base class, you can only have references
|
|
Packit Service |
c5cf8c |
to a Comm.*/
|
|
Packit Service |
c5cf8c |
int MTestGetComm(MPI::Comm ** comm, int min_size)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int idx;
|
|
Packit Service |
c5cf8c |
static int getinter = 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!getinter) {
|
|
Packit Service |
c5cf8c |
MPI::Intracomm rcomm;
|
|
Packit Service |
c5cf8c |
idx = MTestGetIntracomm(rcomm, min_size);
|
|
Packit Service |
c5cf8c |
if (idx == 0) {
|
|
Packit Service |
c5cf8c |
getinter = 1;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
MPI::Intracomm * ncomm = new MPI::Intracomm(rcomm);
|
|
Packit Service |
c5cf8c |
*comm = ncomm;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (getinter) {
|
|
Packit Service |
c5cf8c |
MPI::Intercomm icomm;
|
|
Packit Service |
c5cf8c |
int isLeft;
|
|
Packit Service |
c5cf8c |
idx = MTestGetIntercomm(icomm, isLeft, min_size);
|
|
Packit Service |
c5cf8c |
if (idx == 0) {
|
|
Packit Service |
c5cf8c |
getinter = 0;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
MPI::Intercomm * ncomm = new MPI::Intercomm(icomm);
|
|
Packit Service |
c5cf8c |
*comm = ncomm;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return idx;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Free a communicator. It may be called with a predefined communicator
|
|
Packit Service |
c5cf8c |
or MPI_COMM_NULL */
|
|
Packit Service |
c5cf8c |
void MTestFreeComm(MPI::Comm & comm)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
if (comm != MPI::COMM_WORLD && comm != MPI::COMM_SELF && comm != MPI::COMM_NULL) {
|
|
Packit Service |
c5cf8c |
comm.Free();
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* ------------------------------------------------------------------------ */
|
|
Packit Service |
c5cf8c |
void MTestPrintError(int errcode)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int errclass, slen;
|
|
Packit Service |
c5cf8c |
char string[MPI_MAX_ERROR_STRING];
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
errclass = MPI::Get_error_class(errcode);
|
|
Packit Service |
c5cf8c |
MPI::Get_error_string(errcode, string, slen);
|
|
Packit Service |
c5cf8c |
cout << "Error class " << errclass << "(" << string << ")\n";
|
|
Packit Service |
c5cf8c |
cout.flush();
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
void MTestPrintErrorMsg(const char msg[], int errcode)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int errclass, slen;
|
|
Packit Service |
c5cf8c |
char string[MPI_MAX_ERROR_STRING];
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
errclass = MPI::Get_error_class(errcode);
|
|
Packit Service |
c5cf8c |
MPI::Get_error_string(errcode, string, slen);
|
|
Packit Service |
c5cf8c |
cout << msg << ": Error class " << errclass << " (" << string << ")\n";
|
|
Packit Service |
c5cf8c |
cout.flush();
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* ------------------------------------------------------------------------ */
|
|
Packit Service |
c5cf8c |
/* Fatal error. Report and exit */
|
|
Packit Service |
c5cf8c |
void MTestError(const char *msg)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
cerr << msg << "\n";
|
|
Packit Service |
c5cf8c |
cerr.flush();
|
|
Packit Service |
c5cf8c |
MPI::COMM_WORLD.Abort(1);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#ifdef HAVE_MPI_WIN_CREATE
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Create MPI Windows
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
static int win_index = 0;
|
|
Packit Service |
c5cf8c |
static const char *winName;
|
|
Packit Service |
c5cf8c |
/* Use an attribute to remember the type of memory allocation (static,
|
|
Packit Service |
c5cf8c |
malloc, or MPI_Alloc_mem) */
|
|
Packit Service |
c5cf8c |
static int mem_keyval = MPI::KEYVAL_INVALID;
|
|
Packit Service |
c5cf8c |
int MTestGetWin(MPI::Win & win, bool mustBePassive)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
static char actbuf[1024];
|
|
Packit Service |
c5cf8c |
static char *pasbuf;
|
|
Packit Service |
c5cf8c |
char *buf;
|
|
Packit Service |
c5cf8c |
int n, rank;
|
|
Packit Service |
c5cf8c |
MPI::Info info;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (mem_keyval == MPI::KEYVAL_INVALID) {
|
|
Packit Service |
c5cf8c |
/* Create the keyval */
|
|
Packit Service |
c5cf8c |
mem_keyval = MPI::Win::Create_keyval(MPI::Win::NULL_COPY_FN, MPI::Win::NULL_DELETE_FN, 0);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
switch (win_index) {
|
|
Packit Service |
c5cf8c |
case 0:
|
|
Packit Service |
c5cf8c |
/* Active target window */
|
|
Packit Service |
c5cf8c |
win = MPI::Win::Create(actbuf, 1024, 1, MPI::INFO_NULL, MPI::COMM_WORLD);
|
|
Packit Service |
c5cf8c |
winName = "active-window";
|
|
Packit Service |
c5cf8c |
win.Set_attr(mem_keyval, (void *) 0);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case 1:
|
|
Packit Service |
c5cf8c |
/* Passive target window */
|
|
Packit Service |
c5cf8c |
pasbuf = (char *) MPI::Alloc_mem(1024, MPI::INFO_NULL);
|
|
Packit Service |
c5cf8c |
win = MPI::Win::Create(pasbuf, 1024, 1, MPI::INFO_NULL, MPI::COMM_WORLD);
|
|
Packit Service |
c5cf8c |
winName = "passive-window";
|
|
Packit Service |
c5cf8c |
win.Set_attr(mem_keyval, (void *) 2);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case 2:
|
|
Packit Service |
c5cf8c |
/* Active target; all windows different sizes */
|
|
Packit Service |
c5cf8c |
rank = MPI::COMM_WORLD.Get_rank();
|
|
Packit Service |
c5cf8c |
n = rank * 64;
|
|
Packit Service |
c5cf8c |
if (n)
|
|
Packit Service |
c5cf8c |
buf = (char *) malloc(n);
|
|
Packit Service |
c5cf8c |
else
|
|
Packit Service |
c5cf8c |
buf = 0;
|
|
Packit Service |
c5cf8c |
win = MPI::Win::Create(buf, n, 1, MPI::INFO_NULL, MPI::COMM_WORLD);
|
|
Packit Service |
c5cf8c |
winName = "active-all-different-win";
|
|
Packit Service |
c5cf8c |
win.Set_attr(mem_keyval, (void *) 1);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case 3:
|
|
Packit Service |
c5cf8c |
/* Active target, no locks set */
|
|
Packit Service |
c5cf8c |
rank = MPI::COMM_WORLD.Get_rank();
|
|
Packit Service |
c5cf8c |
n = rank * 64;
|
|
Packit Service |
c5cf8c |
if (n)
|
|
Packit Service |
c5cf8c |
buf = (char *) malloc(n);
|
|
Packit Service |
c5cf8c |
else
|
|
Packit Service |
c5cf8c |
buf = 0;
|
|
Packit Service |
c5cf8c |
info = MPI::Info::Create();
|
|
Packit Service |
c5cf8c |
info.Set("nolocks", "true");
|
|
Packit Service |
c5cf8c |
win = MPI::Win::Create(buf, n, 1, info, MPI::COMM_WORLD);
|
|
Packit Service |
c5cf8c |
info.Free();
|
|
Packit Service |
c5cf8c |
winName = "active-nolocks-all-different-win";
|
|
Packit Service |
c5cf8c |
win.Set_attr(mem_keyval, (void *) 1);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
default:
|
|
Packit Service |
c5cf8c |
win_index = -1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
win_index++;
|
|
Packit Service |
c5cf8c |
return win_index;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Return a pointer to the name associated with a window object */
|
|
Packit Service |
c5cf8c |
const char *MTestGetWinName(void)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return winName;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Free the storage associated with a window object */
|
|
Packit Service |
c5cf8c |
void MTestFreeWin(MPI::Win & win)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
void *addr;
|
|
Packit Service |
c5cf8c |
bool flag;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
flag = win.Get_attr(MPI_WIN_BASE, &addr);
|
|
Packit Service |
c5cf8c |
if (!flag) {
|
|
Packit Service |
c5cf8c |
MTestError("Could not get WIN_BASE from window");
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (addr) {
|
|
Packit Service |
c5cf8c |
void *val;
|
|
Packit Service |
c5cf8c |
flag = win.Get_attr(mem_keyval, &val;;
|
|
Packit Service |
c5cf8c |
if (flag) {
|
|
Packit Service |
c5cf8c |
if (val == (void *) 1) {
|
|
Packit Service |
c5cf8c |
free(addr);
|
|
Packit Service |
c5cf8c |
} else if (val == (void *) 2) {
|
|
Packit Service |
c5cf8c |
MPI::Free_mem(addr);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* if val == (void *)0, then static data that must not be freed */
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
win.Free();
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static void MTestRMACleanup(void)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
if (mem_keyval != MPI::KEYVAL_INVALID) {
|
|
Packit Service |
c5cf8c |
MPI::Win::Free_keyval(mem_keyval);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#else
|
|
Packit Service |
c5cf8c |
static void MTestRMACleanup(void)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif
|