|
Packit |
0848f5 |
/* -*- Mode: C++; c-basic-offset:4 ; -*- */
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* (C) 2003 by Argonne National Laboratory.
|
|
Packit |
0848f5 |
* See COPYRIGHT in top-level directory.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
#include "mpi.h"
|
|
Packit |
0848f5 |
#include "mpitestconf.h"
|
|
Packit |
0848f5 |
#ifdef HAVE_IOSTREAM
|
|
Packit |
0848f5 |
// Not all C++ compilers have iostream instead of iostream.h
|
|
Packit |
0848f5 |
#include <iostream>
|
|
Packit |
0848f5 |
#ifdef HAVE_NAMESPACE_STD
|
|
Packit |
0848f5 |
// Those that do need the std namespace; otherwise, a bare "cout"
|
|
Packit |
0848f5 |
// is likely to fail to compile
|
|
Packit |
0848f5 |
using namespace std;
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
#else
|
|
Packit |
0848f5 |
#include <iostream.h>
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
#include "mpitestcxx.h"
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
static char MTEST_Descrip[] = "A simple test of Comm_spawn, followed by intercomm merge";
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
int main( int argc, char *argv[] )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int errs = 0, err;
|
|
Packit |
0848f5 |
int rank, size, rsize, i;
|
|
Packit |
0848f5 |
int np = 2;
|
|
Packit |
0848f5 |
int errcodes[2];
|
|
Packit |
0848f5 |
MPI::Intercomm parentcomm, intercomm;
|
|
Packit |
0848f5 |
MPI::Intracomm intracomm, intracomm2, intracomm3;
|
|
Packit |
0848f5 |
bool isChild = false;
|
|
Packit |
0848f5 |
MPI::Status status;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MTest_Init( );
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
parentcomm = MPI::Comm::Get_parent();
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (parentcomm == MPI::COMM_NULL) {
|
|
Packit |
0848f5 |
/* Create 2 more processes */
|
|
Packit |
0848f5 |
intercomm = MPI::COMM_WORLD.Spawn( "./spawnintrax", MPI::ARGV_NULL, np,
|
|
Packit |
0848f5 |
MPI::INFO_NULL, 0, errcodes );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else
|
|
Packit |
0848f5 |
intercomm = parentcomm;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* We now have a valid intercomm */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
rsize = intercomm.Get_remote_size( );
|
|
Packit |
0848f5 |
size = intercomm.Get_size();
|
|
Packit |
0848f5 |
rank = intercomm.Get_rank();
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (parentcomm == MPI::COMM_NULL) {
|
|
Packit |
0848f5 |
/* Master */
|
|
Packit |
0848f5 |
if (rsize != np) {
|
|
Packit |
0848f5 |
errs++;
|
|
Packit |
0848f5 |
cout << "Did not create " << np << " processes (got " <<
|
|
Packit |
0848f5 |
rsize << ")\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (rank == 0) {
|
|
Packit |
0848f5 |
for (i=0; i
|
|
Packit |
0848f5 |
intercomm.Send( &i, 1, MPI::INT, i, 0 );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
/* Child */
|
|
Packit |
0848f5 |
isChild = true;
|
|
Packit |
0848f5 |
if (size != np) {
|
|
Packit |
0848f5 |
errs++;
|
|
Packit |
0848f5 |
cout << "(Child) Did not create " << np <<
|
|
Packit |
0848f5 |
" processes (got " << size << ")\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
intercomm.Recv( &i, 1, MPI::INT, 0, 0, status );
|
|
Packit |
0848f5 |
if (i != rank) {
|
|
Packit |
0848f5 |
errs++;
|
|
Packit |
0848f5 |
cout << "Unexpected rank on child " << rank << " (" <<
|
|
Packit |
0848f5 |
i << ")\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* At this point, try to form the intracommunicator */
|
|
Packit |
0848f5 |
intracomm = intercomm.Merge( isChild );
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Check on the intra comm */
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int icsize, icrank, wrank;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
icsize = intracomm.Get_size();
|
|
Packit |
0848f5 |
icrank = intracomm.Get_rank();
|
|
Packit |
0848f5 |
wrank = MPI::COMM_WORLD.Get_rank();
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (icsize != rsize + size) {
|
|
Packit |
0848f5 |
errs++;
|
|
Packit |
0848f5 |
cout << "Intracomm rank " << icrank << " thinks size is " <<
|
|
Packit |
0848f5 |
icsize << ", not " << rsize + size << "\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
/* Make sure that the processes are ordered correctly */
|
|
Packit |
0848f5 |
if (isChild) {
|
|
Packit |
0848f5 |
int psize;
|
|
Packit |
0848f5 |
psize = parentcomm.Get_remote_size();
|
|
Packit |
0848f5 |
if (icrank != psize + wrank ) {
|
|
Packit |
0848f5 |
errs++;
|
|
Packit |
0848f5 |
cout << "Intracomm rank " << icrank <<
|
|
Packit |
0848f5 |
" (from child) should have rank " << psize + wrank << "\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
if (icrank != wrank) {
|
|
Packit |
0848f5 |
errs++;
|
|
Packit |
0848f5 |
cout << "Intracomm rank " << icrank <<
|
|
Packit |
0848f5 |
" (from parent) should have rank " << wrank << "\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* At this point, try to form the intracommunicator, with the other
|
|
Packit |
0848f5 |
processes first */
|
|
Packit |
0848f5 |
intracomm2 = intercomm.Merge( !isChild );
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Check on the intra comm */
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int icsize, icrank, wrank;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
icsize = intracomm2.Get_size();
|
|
Packit |
0848f5 |
icrank = intracomm2.Get_rank();
|
|
Packit |
0848f5 |
wrank = MPI::COMM_WORLD.Get_rank();
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (icsize != rsize + size) {
|
|
Packit |
0848f5 |
errs++;
|
|
Packit |
0848f5 |
cout << "(2)Intracomm rank " << icrank <<
|
|
Packit |
0848f5 |
" thinks size is " << icsize << ", not " << rsize + size <<
|
|
Packit |
0848f5 |
"\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
/* Make sure that the processes are ordered correctly */
|
|
Packit |
0848f5 |
if (isChild) {
|
|
Packit |
0848f5 |
if (icrank != wrank ) {
|
|
Packit |
0848f5 |
errs++;
|
|
Packit |
0848f5 |
cout << "(2)Intracomm rank " << icrank <<
|
|
Packit |
0848f5 |
" (from child) should have rank " << wrank << "\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
int csize;
|
|
Packit |
0848f5 |
csize = intercomm.Get_remote_size();
|
|
Packit |
0848f5 |
if (icrank != wrank + csize) {
|
|
Packit |
0848f5 |
errs++;
|
|
Packit |
0848f5 |
cout << "(2)Intracomm rank " << icrank <<
|
|
Packit |
0848f5 |
" (from parent) should have rank " << wrank + csize <<
|
|
Packit |
0848f5 |
"\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* At this point, try to form the intracommunicator, with an
|
|
Packit |
0848f5 |
arbitrary choice for the first group of processes */
|
|
Packit |
0848f5 |
intracomm3 = intercomm.Merge( false );
|
|
Packit |
0848f5 |
/* Check on the intra comm */
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int icsize, icrank, wrank;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
icsize = intracomm3.Get_size();
|
|
Packit |
0848f5 |
icrank = intracomm3.Get_rank();
|
|
Packit |
0848f5 |
wrank = MPI::COMM_WORLD.Get_rank();
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (icsize != rsize + size) {
|
|
Packit |
0848f5 |
errs++;
|
|
Packit |
0848f5 |
cout << "(3)Intracomm rank " << icrank <<
|
|
Packit |
0848f5 |
" thinks size is " << icsize << ", not " << rsize + size <<
|
|
Packit |
0848f5 |
"\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
/* Eventually, we should test that the processes are ordered
|
|
Packit |
0848f5 |
correctly, by groups (must be one of the two cases above) */
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Update error count */
|
|
Packit |
0848f5 |
if (isChild) {
|
|
Packit |
0848f5 |
/* Send the errs back to the master process */
|
|
Packit |
0848f5 |
intercomm.Ssend( &errs, 1, MPI::INT, 0, 1 );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
if (rank == 0) {
|
|
Packit |
0848f5 |
/* We could use intercomm reduce to get the errors from the
|
|
Packit |
0848f5 |
children, but we'll use a simpler loop to make sure that
|
|
Packit |
0848f5 |
we get valid data */
|
|
Packit |
0848f5 |
for (i=0; i
|
|
Packit |
0848f5 |
intercomm.Recv( &err, 1, MPI::INT, i, 1 );
|
|
Packit |
0848f5 |
errs += err;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* It isn't necessary to free the intracomms, but it should not hurt */
|
|
Packit |
0848f5 |
intracomm.Free();
|
|
Packit |
0848f5 |
intracomm2.Free();
|
|
Packit |
0848f5 |
intracomm3.Free();
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* It isn't necessary to free the intercomm, but it should not hurt */
|
|
Packit |
0848f5 |
intercomm.Free();
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Note that the MTest_Finalize get errs only over COMM_WORLD */
|
|
Packit |
0848f5 |
/* Note also that both the parent and child will generate "No Errors"
|
|
Packit |
0848f5 |
if both call MTest_Finalize */
|
|
Packit |
0848f5 |
if (parentcomm == MPI::COMM_NULL) {
|
|
Packit |
0848f5 |
MTest_Finalize( errs );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPI::Finalize();
|
|
Packit |
0848f5 |
return 0;
|
|
Packit |
0848f5 |
}
|