将非 NULL argv 传递给 MPI_Comm_spawn

Passing non-NULL argv to MPI_Comm_spawn

假设我的程序(我们称之为 prog_A)作为单个 MPI 进程启动。 后来我希望程序 prog_A 使用 MPI_Comm_spawn 和我传递给 prog_A 的相同参数来生成 n MPI 进程(让我们称它们为 prog_B)。

例如,如果我 运行 prog_A 参数 200 100 10

mpiexec -n 1 prog_A 200 100 10

我希望为 prog_B 提供相同的参数 200 100 10

我该怎么做?我尝试了以下但它不起作用。

  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();

你的问题是你没有 NULL 终止你的 argv 列表。这是 MPI standard 的重要部分(强调已添加):

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.

您只需在列表末尾添加一个 NULL。这是更正后的代码(翻译成 C,因为我的笔记本电脑上没有安装 C++ 绑定):

#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();
}

您根本不需要复制参数向量。您所要做的就是利用 C99 标准的规定,该标准要求 argv 应该以 NULL 结尾:

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();

注意使用 argv+1 以跳过第一个参数(程序名称)。该代码的好处是它可以处理传递给原始程序的任意数量的参数。