Blame test/mpi/threads/spawn/multispawn.c

Packit 0848f5
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit 0848f5
/*
Packit 0848f5
 *
Packit 0848f5
 *  (C) 2008 by Argonne National Laboratory.
Packit 0848f5
 *      See COPYRIGHT in top-level directory.
Packit 0848f5
 */
Packit 0848f5
/*
Packit 0848f5
 * This (is a placeholder for a) test that creates 4 threads, each of which
Packit 0848f5
 * does a concurrent spawn of 4 more processes, for a total of 17 MPI processes
Packit 0848f5
 * The resulting intercomms are tested for consistency (to ensure that the
Packit 0848f5
 * spawns didn't get confused among the threads).
Packit 0848f5
 *
Packit 0848f5
 * As an option, it will time the Spawn calls.  If the spawn calls block the
Packit 0848f5
 * calling thread, this may show up in the timing of the calls
Packit 0848f5
 */
Packit 0848f5
Packit 0848f5
#include "mpi.h"
Packit 0848f5
#include <stdio.h>
Packit 0848f5
#include <stdlib.h>
Packit 0848f5
#include "mpitest.h"
Packit 0848f5
#include "mpithreadtest.h"
Packit 0848f5
Packit 0848f5
/*
Packit 0848f5
static char MTEST_Descrip[] = "Spawn jobs from multiple threads";
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
#define NTHREADS 4
Packit 0848f5
#define NPERTHREAD 4
Packit 0848f5
int activeThreads = 0;
Packit 0848f5
Packit 0848f5
MPI_Comm intercomms[NTHREADS];
Packit 0848f5
Packit 0848f5
MTEST_THREAD_RETURN_TYPE spawnProcess(void *p);
Packit 0848f5
Packit 0848f5
MTEST_THREAD_RETURN_TYPE spawnProcess(void *p)
Packit 0848f5
{
Packit 0848f5
    int rank, i;
Packit 0848f5
    int errcodes[NPERTHREAD];
Packit 0848f5
Packit 0848f5
    MPI_Comm_rank(MPI_COMM_WORLD, &rank;;
Packit 0848f5
Packit 0848f5
    /* The thread number is passed into this routine through the value of the
Packit 0848f5
     * argument */
Packit 0848f5
    i = (int) (long) p;
Packit 0848f5
Packit 0848f5
    /* Synchronize */
Packit 0848f5
    MTest_thread_barrier(NTHREADS);
Packit 0848f5
Packit 0848f5
    /* Spawn */
Packit 0848f5
    MPI_Comm_spawn((char *) "./multispawn", MPI_ARGV_NULL, NPERTHREAD,
Packit 0848f5
                   MPI_INFO_NULL, 0, MPI_COMM_SELF, &intercomms[i], errcodes);
Packit 0848f5
Packit 0848f5
    MPI_Bcast(&i, 1, MPI_INT, MPI_ROOT, intercomms[i]);
Packit 0848f5
Packit 0848f5
    return MTEST_THREAD_RETVAL_IGN;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
int main(int argc, char *argv[])
Packit 0848f5
{
Packit 0848f5
    int rank, size, i, wasParent = 0;
Packit 0848f5
    int provided;
Packit 0848f5
    int err;
Packit 0848f5
    MPI_Comm parentcomm;
Packit 0848f5
Packit 0848f5
    MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
Packit 0848f5
Packit 0848f5
    MPI_Comm_rank(MPI_COMM_WORLD, &rank;;
Packit 0848f5
    MPI_Comm_size(MPI_COMM_WORLD, &size);
Packit 0848f5
Packit 0848f5
    if (provided != MPI_THREAD_MULTIPLE) {
Packit 0848f5
        if (rank == 0) {
Packit 0848f5
            printf
Packit 0848f5
                ("MPI_Init_thread must return MPI_THREAD_MULTIPLE in order for this test to run.\n");
Packit 0848f5
            fflush(stdout);
Packit 0848f5
        }
Packit 0848f5
        MPI_Finalize();
Packit 0848f5
        return -1;
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    MPI_Comm_get_parent(&parentcomm);
Packit 0848f5
    if (parentcomm == MPI_COMM_NULL) {
Packit 0848f5
        wasParent = 1;
Packit 0848f5
Packit 0848f5
        err = MTest_thread_barrier_init();
Packit 0848f5
        if (err) {
Packit 0848f5
            printf("barrier_init failed\n");
Packit 0848f5
            fflush(stdout);
Packit 0848f5
            MPI_Finalize();
Packit 0848f5
            return 1;
Packit 0848f5
        }
Packit 0848f5
Packit 0848f5
        for (i = 0; i < NTHREADS - 1; i++) {
Packit 0848f5
            MTest_Start_thread(spawnProcess, (void *) (long) i);
Packit 0848f5
        }
Packit 0848f5
Packit 0848f5
        /* spawn the processes */
Packit 0848f5
        spawnProcess((void *) (NTHREADS - 1));
Packit 0848f5
Packit 0848f5
        /* Exit the threads (but the spawned processes remain) */
Packit 0848f5
        MTest_Join_threads();
Packit 0848f5
Packit 0848f5
        err = MTest_thread_barrier_free();
Packit 0848f5
        if (err) {
Packit 0848f5
            printf("barrier_free failed\n");
Packit 0848f5
            fflush(stdout);
Packit 0848f5
            MPI_Finalize();
Packit 0848f5
            return 1;
Packit 0848f5
        }
Packit 0848f5
Packit 0848f5
        /* The master thread (this thread) checks the created communicators */
Packit 0848f5
        for (i = 0; i < NTHREADS; i++) {
Packit 0848f5
            MPI_Bcast(&i, 1, MPI_INT, MPI_ROOT, intercomms[i]);
Packit 0848f5
        }
Packit 0848f5
Packit 0848f5
        /* Free the created processes */
Packit 0848f5
        for (i = 0; i < NTHREADS; i++) {
Packit 0848f5
            MPI_Comm_disconnect(&intercomms[i]);
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
    else {
Packit 0848f5
        int num, threadnum;
Packit 0848f5
Packit 0848f5
        /* I'm the created process */
Packit 0848f5
        MPI_Bcast(&threadnum, 1, MPI_INT, 0, parentcomm);
Packit 0848f5
Packit 0848f5
        /* Form an intra comm with my parent */
Packit 0848f5
Packit 0848f5
        /* receive from my parent */
Packit 0848f5
        MPI_Bcast(&num, 1, MPI_INT, 0, parentcomm);
Packit 0848f5
Packit 0848f5
        if (num != threadnum) {
Packit 0848f5
            fprintf(stderr, "Unexpected thread num (%d != %d)\n", threadnum, num);
Packit 0848f5
        }
Packit 0848f5
Packit 0848f5
        /* Let the parent free the intercomms */
Packit 0848f5
        MPI_Comm_disconnect(&parentcomm);
Packit 0848f5
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    if (wasParent)
Packit 0848f5
        MTest_Finalize(0);
Packit 0848f5
Packit 0848f5
    MPI_Finalize();
Packit 0848f5
    return 0;
Packit 0848f5
}