Blame test/mpi/cxx/spawn/spawnintrax.cxx

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
}