⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpiexec.c

📁 fortran并行计算包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//*   *  (C) 2004 by Argonne National Laboratory. *      See COPYRIGHT in top-level directory. *//* OWNER=gropp *//* An example mpiexec program that uses a remote shell program to create   new processes on the selected hosts.   This code also shows how to use the pmutil routines (in ../util)    to provide many of the services required by mpiexec    Steps:   1. Read and process that command line.  Build a ProcessList.  (A ProcessList   may have one entry for a request to create n separate processes)      2. Convert the ProcessList into a ProcessTable.  In the forker mpiexec,   this simply expands the requested number of processes into an    array with one entry per process.  These entries contain information   on both the setup of the processes and the file descriptors used for   stdin,out,err, and for the PMI calls.   3. (Optionally) allow the forked processes to use a host:port to    contact this program, rather than just sharing a pipe.  This allows the   forker to start other programs, such as debuggers.   4. Establish a signal handler for SIGCHLD.  This will allow us to    get information about process termination; in particular, the exit   status.   5. Start the programs.   6. Process input from the programs; send stdin given to this process    to the selected processes (usually rank 0 or everyone).  Handle all    PMI commands, including spawn.  Another "input" is the expiration of the   specified timelimit for the run, if any.   7. Process rundown commands and handle any abnormal termination.     8. Wait for any processes to exit; gather the exit status and reason   for exit (if abnormal, such as signaled with SEGV or BUS)   9. Release all resources and compute the exit status for this program   (using one of several approaches, such as taking the maximum of the   exit statuses).  Special Case to support Singleton Init:  To support a singleton init of a process that then wants to   create processes with MPI_Comm_spawn(_multiple), a special form of  mpiexec is supported:       mpiexec -pmi_args <port> <interfacename> <securitykey> <pid>  The singleton process (in a routine in simple_pmi.c) forks a process and  execs mpiexe with these arguments, where port is the port to which   mpiexec should connect, interfacename is the name of the network interface  (BUG: may not be correctly set as mpd currently ignores it), securitykey  is a place-holder for a key used by the singleton init process to verify  that the process connecting on the port is the one that was intended, and  pid is the pid of the singleton init process.  FIXME: The above has not been implemented yet.*/#include "remshellconf.h"#include <stdio.h>#include <string.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <stdlib.h>#include "pmutil.h"#include "process.h"#include "cmnargs.h"#include "pmiserv.h"#include "ioloop.h"#include "labelout.h"#include "rm.h"#include "simple_pmiutil.h"#include "env.h"             /* MPIE_Putenv *//* mpimem.h contains prototypes for MPIU_Strncpy etc. */#include "mpimem.h"typedef struct { PMISetup pmiinfo; IOLabelSetup labelinfo; } SetupInfo;/* Forward declarations */int mypreamble( void *, ProcessState* );int mypostfork( void *, void *, ProcessState* );int mypostamble( void *, void *, ProcessState* );int myspawn( ProcessWorld *, void * );static int AddEnvSetToCmdLine( const char *, const char *, const char ** );/* Set printFailure to 1 to get an explanation of the failure reason   for each process when a process fails */static int printFailure = 0;#ifndef MAX_PORT_STRING#define MAX_PORT_STRING 1024#endif/* Note that envp is common but not standard */int main( int argc, char *argv[], char *envp[] ){    int          rc;    int          erc = 0;  /* Other (exceptional) return codes */    int          reason, signaled = 0;    SetupInfo    s;    char         portString[MAX_PORT_STRING];    /* MPIE_ProcessInit initializes the global pUniv */    MPIE_ProcessInit();    /* Set a default for the universe size */    pUniv.size = 64;    /* Set defaults for any arguments that are options.  Also check the       environment for special options, such as debugging.  Set        some defaults in pUniv */    MPIE_CheckEnv( &pUniv, 0, 0 );    IOLabelCheckEnv( );    /* Handle the command line arguments.  Use the routine from util/cmnargs.c       to fill in the universe */    MPIE_Args( argc, argv, &pUniv, 0, 0 );    /* If there were any soft arguments, we need to handle them now */    rc = MPIE_InitWorldWithSoft( &pUniv.worlds[0], pUniv.size );    if (!rc) {	MPIU_Error_printf( "Unable to process soft arguments\n" );	exit(1);    }    if (pUniv.fromSingleton) {	/* The MPI process is already running.  We create a simple entry	   for a single process rather than creating the process */	MPIE_SetupSingleton( &pUniv );    }    rc = MPIE_ChooseHosts( &pUniv.worlds[0], MPIE_ReadMachines, 0 );    if (rc) {	MPIU_Error_printf( "Unable to assign hosts to processes\n" );	exit(1);    }    if (MPIE_Debug) MPIE_PrintProcessUniverse( stdout, &pUniv );    DBG_PRINTF( ("timeout_seconds = %d\n", pUniv.timeout) );    /* Get the common port for creating PMI connections to the created       processes */    rc = PMIServSetupPort( &pUniv, portString, sizeof(portString) );    if (rc) {	MPIU_Error_printf( "Unable to setup port for listener\n" );	exit(1);    }    s.pmiinfo.portName = portString;#ifdef USE_MPI_STAGE_EXECUTABLES    /* Hook for later use in staging executables */    if (?stageExes) {	rc = MPIE_StageExecutables( &pUniv.worlds[0] );	if (!rc) ...;    }#endif    PMIServInit(myspawn,&s);    s.pmiinfo.pWorld = &pUniv.worlds[0];    PMISetupNewGroup( pUniv.worlds[0].nProcess, 0 );    MPIE_ForwardCommonSignals();     if (!pUniv.fromSingleton) {	MPIE_ForkProcesses( &pUniv.worlds[0], envp, mypreamble, &s,			mypostfork, 0, mypostamble, 0 );    }    else {	/* FIXME: The singleton code goes here */	MPIU_Error_printf( "Singleton init not supported\n" );	exit(1);    }    reason = MPIE_IOLoop( pUniv.timeout );    if (reason == IOLOOP_TIMEOUT) {	/* Exited due to timeout.  Generate an error message and	   terminate the children */	if (pUniv.timeout > 60) {	    MPIU_Error_printf( "Timeout of %d minutes expired; job aborted\n",			       pUniv.timeout / 60 );	}	else {	    MPIU_Error_printf( "Timeout of %d seconds expired; job aborted\n",			       pUniv.timeout );	}	erc = 1;	MPIE_KillUniverse( &pUniv );    }    /* Wait for all processes to exit and gather information on them.       We do this through the SIGCHLD handler. We also bound the length       of time that we wait to 2 seconds.    */    MPIE_WaitForProcesses( &pUniv, 2 );    /* Compute the return code (max for now) */    rc = MPIE_ProcessGetExitStatus( &signaled );    /* Optionally provide detailed information about failed processes */    if ( (rc && printFailure) || signaled) 	MPIE_PrintFailureReasons( stderr );    /* If the processes exited normally (or were already gone) but we       had an exceptional exit, such as a timeout, use the erc value */    if (!rc && erc) rc = erc;    return( rc );}void mpiexec_usage( const char *msg ){    if (msg) {	MPIU_Error_printf( msg );	if (msg[strlen(msg)-1] != '\n') {	    MPIU_Error_printf( "\n" );	}    }    MPIU_Usage_printf( "Usage: mpiexec %s\n", MPIE_ArgDescription() );    exit( -1 );}/* Redirect stdout and stderr to a handler */int mypreamble( void *data, ProcessState *pState ){    SetupInfo *s = (SetupInfo *)data;    int       rc;    IOLabelSetupFDs( &s->labelinfo );    rc = PMISetupSockets( 1, &s->pmiinfo );    /* We must use communication over the socket, rather than the        environment, to pass initialization data */    pState->initWithEnv = 0;        return rc;}/* Close one side of each pipe pair and replace stdout/err with the pipes */int mypostfork( void *predata, void *data, ProcessState *pState ){    SetupInfo *s = (SetupInfo *)predata;    int curarg=0;    IOLabelSetupInClient( &s->labelinfo );    PMISetupInClient( 1, &s->pmiinfo );    /* Now, we *also* change the process state to insert the        interposed remote shell routine.  This is probably not       where we want this in the final version (because MPIE_ExecProgram       does a lot under the assumption that the started program will

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -