Reputation: 2071
Suppose that my program (let's call it prog_A
) starts as a single MPI process.
And later I want program prog_A
to spawn n
MPI processes (let's call them prog_B
) using MPI_Comm_spawn
with the same arguments I passed to prog_A
.
For example, if I run prog_A
with the arguments 200 100 10
mpiexec -n 1 prog_A 200 100 10
I want prog_B
to be provided with the same argments 200 100 10
.
How can I do this? I tried the following but it does not work.
char ** newargv = new char*[3];//create new argv for childs
newargv[0] = new char[50];
newargv[1] = new char[50];
newargv[2] = new char[50];
strcpy(newargv[0],argv[1]);//copy argv to newargv
strcpy(newargv[1],argv[2]);
strcpy(newargv[2],argv[3]);
MPI_Comm theother;
MPI_Init(&argc, &argv);
MPI_Comm_spawn("prog_B",newargv,numchildprocs,
MPI_INFO_NULL, 0, MPI_COMM_SELF, &theother,
MPI_ERRCODES_IGNORE);
MPI_Finalize();
Upvotes: 1
Views: 706
Reputation: 74395
You do not need to copy the argument vector at all. All you have to do is make use of the provisions of the C99 standard, which requires that argv
should be NULL-terminated:
MPI_Comm theother;
// Passing &argc and &argv here is a thing of the past (MPI-1)
MPI_Init(NULL, NULL);
MPI_Comm_spawn("prog_B", argv+1, numchildprocs,
MPI_INFO_NULL, 0, MPI_COMM_SELF, &theother,
MPI_ERRCODES_IGNORE);
MPI_Finalize();
Note the use of argv+1
in order to skip over the first argument (the program name). The benefit of that code is that it works with any number of arguments passed to the original program.
Upvotes: 2
Reputation: 9072
Your problem is that you didn't NULL
terminate your argv list. Here's the important part of the MPI standard (emphasis added):
The argv argument argv is an array of strings containing arguments that are passed to the program. The first element of argv is the first argument passed to command, not, as is conventional in some contexts, the command itself. The argument list is terminated by NULL in C and C++ and an empty string in Fortran. In Fortran, leading and trailing spaces are always stripped, so that a string consisting of all spaces is considered an empty string. The constant MPI_ARGV_NULL may be used in C, C++ and Fortran to indicate an empty argument list. In C and C++, this constant is the same as NULL.
You just need to add a NULL to the end of your list. Here's the corrected code (translated to C since I didn't have the C++ bindings installed on my laptop):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
int main(int argc, char ** argv) {
char ** newargv = malloc(sizeof(char *)*4);//create new argv for childs
int numchildprocs = 1;
MPI_Comm theother;
MPI_Init(&argc, &argv);
MPI_Comm_get_parent(&theother);
if (MPI_COMM_NULL != theother) {
fprintf(stderr, "SPAWNED!\n");
} else {
newargv[0] = (char *) malloc(sizeof(char)*50);
newargv[1] = (char *) malloc(sizeof(char)*50);
newargv[2] = (char *) malloc(sizeof(char)*50);
newargv[3] = NULL;
strncpy(newargv[0],argv[1], 50);//copy argv to newargv
strncpy(newargv[1],argv[2], 50);
strncpy(newargv[2],argv[3], 50);
fprintf(stderr, "SPAWNING!\n");
MPI_Comm_spawn("./prog_B",newargv,numchildprocs,
MPI_INFO_NULL, 0, MPI_COMM_SELF, &theother,
MPI_ERRCODES_IGNORE);
}
MPI_Comm_free(&theother);
MPI_Finalize();
}
Upvotes: 2