将非NULL argv传递给MPI_Comm_spawn

Passing non-NULL argv to MPI_Comm_spawn

本文关键字:MPI Comm spawn NULL argv 将非      更新时间:2023-10-16

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

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

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标准的重要部分(重点添加):

argv参数argv是包含参数的字符串数组传递给程序。argv的第一个元素是传递给命令的参数,而不是像某些上下文中的传统情况那样,命令本身参数列表在C和C++和Fortran中的一个空字符串在Fortran中,前导和尾随空间总是被剥离的,因此由所有空间组成的字符串被认为是一个空字符串。可以使用常量MPI_ARGV_NULL在C、C++和Fortran中,表示一个空的参数列表。在C和C++,此常量与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跳过第一个参数(程序名称)。该代码的好处是,它可以处理传递给原始程序的任意数量的参数。