File: spawnmanyarg.c

package info (click to toggle)
mpich 4.0.2-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 423,384 kB
  • sloc: ansic: 1,088,434; cpp: 71,364; javascript: 40,763; f90: 22,829; sh: 17,463; perl: 14,773; xml: 14,418; python: 10,265; makefile: 9,246; fortran: 8,008; java: 4,355; asm: 324; ruby: 176; lisp: 19; php: 8; sed: 4
file content (180 lines) | stat: -rw-r--r-- 5,785 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
 * Copyright (C) by Argonne National Laboratory
 *     See COPYRIGHT in top-level directory
 */

#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include "mpitest.h"
#include "mpitestconf.h"
#ifdef HAVE_STRING_H
#include <string.h>
#endif

/*
static char MTEST_Descrip[] = "A simple test of Comm_spawn, with many arguments";
*/

#define MAX_ARGV 1024
int worker(int argc, char *argv[], MPI_Comm intercomm, char *outargv[], int np);

int main(int argc, char *argv[])
{
    int errs = 0, err;
    int rank, size, rsize, i;
    int np = 2;
    int errcodes[2];
    MPI_Comm parentcomm, intercomm;
    char *inargv[MAX_ARGV];
    char *outargv[MAX_ARGV];
    int narg = 40;
    char *saveArgp = 0;
    int can_spawn;

    MTest_Init(&argc, &argv);

    errs += MTestSpawnPossible(&can_spawn);

    if (can_spawn) {
        /* Initialize the argument vectors */
        for (i = 0; i < MAX_ARGV; i++) {
            char *p;
            p = (char *) malloc(9);
            if (!p) {
                fprintf(stderr, "Unable to allocated memory\n");
                MPI_Abort(MPI_COMM_WORLD, 1);
            }
            strcpy(p, "01234567");
            inargv[i] = p;
            p = (char *) malloc(9);
            if (!p) {
                fprintf(stderr, "Unable to allocated memory\n");
                MPI_Abort(MPI_COMM_WORLD, 1);
            }
            strcpy(p, "01234567");
            outargv[i] = p;
        }

        MPI_Comm_get_parent(&parentcomm);

        if (parentcomm == MPI_COMM_NULL) {
            for (narg = 16; narg < 512; narg += narg) {
                /* Create 2 more processes */
                /* Set a null at argument length narg */
                saveArgp = inargv[narg];
                inargv[narg] = 0;
                /* ./ is unix specific .
                 * The more generic approach would be to specify "spawnmanyarg" as
                 * the executable and pass an info with ("path", ".") */
                MPI_Comm_spawn((char *) "./spawnmanyarg", inargv, np,
                               MPI_INFO_NULL, 0, MPI_COMM_WORLD, &intercomm, errcodes);
                inargv[narg] = saveArgp;
                /* We now have a valid intercomm */

                /* Parent */
                MPI_Comm_remote_size(intercomm, &rsize);
                MPI_Comm_size(intercomm, &size);
                MPI_Comm_rank(intercomm, &rank);

                if (rsize != np) {
                    errs++;
                    printf("Did not create %d processes (got %d)\n", np, rsize);
                }
                /* Send the expected rank */
                for (i = 0; i < rsize; i++) {
                    MPI_Send(&i, 1, MPI_INT, i, 0, intercomm);
                }
                /* Send the number of arguments */
                for (i = 0; i < rsize; i++) {
                    MPI_Send(&narg, 1, MPI_INT, i, 0, intercomm);
                }
                /* We could use intercomm reduce to get the errors from the
                 * children, but we'll use a simpler loop to make sure that
                 * we get valid data */
                for (i = 0; i < rsize; i++) {
                    MPI_Recv(&err, 1, MPI_INT, i, 1, intercomm, MPI_STATUS_IGNORE);
                    errs += err;
                }

                /* Free the intercomm before the next round of spawns */
                MPI_Comm_free(&intercomm);
            }
        } else {
            /* Note that worker also send errs to the parent */
            errs += worker(argc, argv, parentcomm, outargv, np);
        }

        /* Note that the MTest_Finalize get errs only over COMM_WORLD */
        if (parentcomm == MPI_COMM_NULL) {
            MTest_Finalize(errs);
        } else {
            MPI_Comm_free(&parentcomm);
            MPI_Finalize();
        }
        /* free the argument vectors */
        for (i = 0; i < MAX_ARGV; i++) {
            free(inargv[i]);
            free(outargv[i]);
        }

    } else {
        MTest_Finalize(errs);
    }

    return MTestReturnValue(errs);
}

/* Call this routine if this process is the spawned child */
int worker(int argc, char *argv[], MPI_Comm intercomm, char *outargv[], int np)
{
    int i, narg;
    int rsize, size, rank;
    int errs = 0;
    char *saveoutArgp = 0;
    MPI_Status status;

    MPI_Comm_remote_size(intercomm, &rsize);
    MPI_Comm_size(intercomm, &size);
    MPI_Comm_rank(intercomm, &rank);

    /* Child */
    /* FIXME: This assumes that stdout is handled for the children
     * (the error count will still be reported to the parent) */
    if (size != np) {
        errs++;
        printf("(Child) Did not create %d processes (got %d)\n", np, size);
    }
    MPI_Recv(&i, 1, MPI_INT, 0, 0, intercomm, &status);
    if (i != rank) {
        errs++;
        printf("Unexpected rank on child %d (%d)\n", rank, i);
    }
    MPI_Recv(&narg, 1, MPI_INT, 0, 0, intercomm, MPI_STATUS_IGNORE);
    saveoutArgp = outargv[narg];
    outargv[narg] = 0;
    /* Check the command line */
    for (i = 1; i < argc; i++) {
        if (!outargv[i - 1]) {
            errs++;
            printf("Wrong number of arguments (%d)\n", argc);
            break;
        }
        if (strcmp(argv[i], outargv[i - 1]) != 0) {
            errs++;
            printf("Found arg %s but expected %s\n", argv[i], outargv[i - 1]);
        }
    }
    if (outargv[i - 1]) {
        /* We had too few args in the spawned command */
        errs++;
        printf("Too few arguments to spawned command (only %d)\n", i);
    }
    /* Restore the argument vector (not necessary in this case, since the
     * worker will exit) */
    outargv[narg] = saveoutArgp;
    /* Send the errs back to the parent process */
    MPI_Ssend(&errs, 1, MPI_INT, 0, 1, intercomm);

    return errs;
}