jeffhammond / miscellaneous-mpi-issues

Tickets for the MPI Forum
http://www.mpi-forum.org/
0 stars 0 forks source link

MPI_INIT with argc/argv support for Fortran 2003+ #2

Open jeffhammond opened 8 years ago

jeffhammond commented 8 years ago

This was https://svn.mpi-forum.org/trac/mpi-forum-web/ticket/351

Motivation

As of Fortran 2003, access to argc/argv is standardized (http://fortranwiki.org/fortran/show/Command-line+arguments). There are good reasons why MPI_INIT processes argc/argv with the C binding. It seems natural to extend this functionality to Fortran by providing a Fortran 2008 binding that processes argc/argv as MPI_INIT does for C, i.e. strips away the mpirun/mpiexec arguments and provides the user the same arguments that they would get with serial (i.e. $ ./myprogram.x) invocation.

Solution

Paste from comments

Miscellany

I don't know if there's a right way to do this or what it is. This ticket is created with the intent to inspire those with real Fortran experise (Rolf, Craig, ...) to tell us if there is a right answer and what it is.

I apologize if this ticket is a duplicate. I didn't search for a prior version of it in the list of tickets. If I've created a duplicate ticket and this reduces your overall happiness, I will compensate you with a beer at the Forum this week or one to be named later.

jeffhammond commented 8 years ago

@jsquyres said:

Craig and I talked about this on the phone. We propose adding 2 MPI subroutines to the mpi_f08 module (NOT to mpif.h or the mpi module or the C bindings), inspired by the F2003 interface. These are different than the F2003 functions so that MPI can modify the argc/argv if it wants to:

MPI_COMMAND_ARGUMENT_COUNT(count, ierror) BIND(C)
  INTEGER, INTENT(OUT) :: count, ierror

Quite similar to the the F2003 command_argument_count function, but the value returned in the count parameter may be adjusted if the MPI implementation is stuffing/extracting argv.

MPI_GET_COMMAND_ARGUMENT(number, value, length, ierror) BIND(C)
  INTEGER, INTENT(IN) :: number
  CHARACTER(len=*), INTENT(OUT) :: value
  INTEGER, INTENT(INOUT) :: length
  INTEGER, INTENT(OUT) :: ierror

Quite similar to the F2003 get_command_argument function, but length is INOUT; MPI will set length to be the number of characters actually used. The caller will know that they got the full string if the output value of length is less than the input value of length.

...alternatively, we can use the same status argument from the F2003 get_command_argument function to tell the user if they got the full string or not. Either is fine with me.

NOTE: We did not simply add arguments to a new MPI_Init overloaded signature in the mpi_f08 module because then the MPI implementation would need to allocate a 2D array of strings, and there's nowhere in the MPI API to free those strings. Plus, the output syntax would be really wonky: the user would have to pass a pointer to a 2D array of strings that the MPI would need to fill in. Ick.

jeffhammond commented 8 years ago

I said:

This is a much better solution that what I originally suggested, particularly since it has zero effect on and does not even need to be read by developers of Fortran codes that do not make use of STDIN.

The Fortran signatures should be trivially modified as follows to make the {{{ierror}}} argument optional, as is done for the other F08 function signatures.

MPI_COMMAND_ARGUMENT_COUNT(count, ierror) BIND(C)
  INTEGER, INTENT(OUT) :: count
  INTEGER, OPTIONAL, INTENT(OUT) ::  ierror
MPI_GET_COMMAND_ARGUMENT(number, value, length, ierror) BIND(C)
  INTEGER, INTENT(IN) :: number
  CHARACTER(len=*), INTENT(OUT) :: value
  INTEGER, INTENT(INOUT) :: length
  INTEGER, OPTIONAL, INTENT(OUT) ::  ierror
jeffhammond commented 8 years ago

@RolfRabenseifner said:

CHARACTER(len=*), INTENT(OUT) :: value 

is not optimal. It is unclear how to handle the case, when length is larger than the size of the passed value.

Please have a look to MPI_INFO_GET_VALUELEN and MPI_INFO_GET, i.e., to have three routines:

I do not expect that the way we did in

MPI_Comm_get_name(comm, comm_name, resultlen, ierror) BIND(C)
  CHARACTER(LEN=MPI_MAX_OBJECT_NAME), INTENT(OUT) :: comm_name

would fit for the MPI_INIT argc/argv arguments.

Please also change in the BIND(C) interface the routine name to the mixed upper/lower case name, i.e., MPI_Command_argument_count(count, ierror) BIND(C)

Upper case must be used only in the old-style Fortran interface and the generic definition.

jeffhammond commented 8 years ago

I said:

Both get_command_argument and get_command have the following behavior (assuming http://fortranwiki.org is correct):

If value can not hold the argument, it is truncated to fit the length of value.

Why should MPI not follow this prescription? This would comply with the principle of least surprise for Fortran 2003+ programmers who know the behavior of these functions.

jeffhammond commented 8 years ago

@RolfRabenseifner said:

I expected truncation in your design, but then, you must specify which length is returned in

INTEGER, INTENT(INOUT) :: length

Is it

With the first option, you get into trouble if you want to handle command arguments of arbitrary length.

You must choose the second option if you want that an application should be able to

If you look at the existing MPI routines, then as far as I oversee, you find two choices:

Are you sure that you want to introduce a third method within the MPI standard to return a string value?

This question is mainly independent from the programming language. I.e., there is no need to restrict your proposed routines to Fortran as long as there is a method to implement them also in C, i.e., without argc/argv passed in MPI_Init.

jeffhammond commented 8 years ago

@jsquyres said:

Jeff's and Rolf's points about my original proposal are correct (optional ierror, mixed-case names, etc.). Here's updates that represent the union of all of these suggestions:

MPI_Command_argument_count(count, ierror) BIND(C)
  INTEGER, INTENT(OUT) :: count
  INTEGER, OPTIONAL, INTENT(OUT) :: ierror

MPI_Get_command_argument(number, value, length, ierror) BIND(C)
  INTEGER, INTENT(IN) :: number
  CHARACTER(len=*), INTENT(OUT) :: value
  INTEGER, INTENT(INOUT) :: length
  INTEGER, OPTIONAL, INTENT(OUT) :: ierror

To be clear, Jeff correctly asserted my intent with this proposal: it echos what already exists in F2003, and is a "least surprise" kind of issue for Fortran programmers.

Indeed, I'm not wild about these MPI subroutine names, but I think it's more important to echo the native F2003 subroutine names.

I had to google around a bit more, but I found this web page which states that get_command_argument's optional "length" argument is actually an OUT parameter (the Fortran wiki doesn't specify), and that upon return, it contains the full length of the string. Hence, this is Rolf's "second option", and therefore a user can know the correct length after a first call to MPI_Get_command_argument. I presume it would be used something like this:

! Call MGCA with a "length" of 0, just to get the actual
! length of the string.
length = 0
MPI_Get_command_argument(i, string, length)

! Now allocate string to be "length" bytes long
...

! Now call MGCA again with a string that is long enough
MPI_Get_command_argument(i, string, length)

I do not believe that attempting to enforce a max length (a la MPI_MAX_OBJECT_NAME) would be a good idea. argv is not controlled by MPI, so we can't impose max limits on it.

jeffhammond commented 8 years ago

@jsquyres said:

Is MPI_INFO_ENV not sufficient? (see MPI-3 p358)

jeffhammond commented 8 years ago

I said:

Page 359:

The info object MPI_INFO_ENV need not contain a (key,value) pair for each of these predefined keys; the set of (key,value) pairs provided is implementation-dependent. Implementations may provide additional, implementation specific, (key,value) pairs.

So, no, it is not sufficient because the standard does not require it. I also don't know if Fortran is able to query the argv option in all cases. What if I call MPI_Init(NULL,NULL); from C?

SamTWhite commented 8 years ago

What would MPI_Get_command_argument return on error?

Per the Fortran2003 standard, 'ierror' is assigned the value -1 if the 'value' argument is present and has a length less than the significant length of the command argument specified by 'number'. It is assigned a processor-dependent positive value if the argument retrieval fails.

jeffhammond commented 8 years ago

@SamTWhite We would use either one of the error codes listed in Table 8.1 or add a new one. We could reuse MPI_ERR_TRUNCATE when the Fortran function returns -1 and MPI_ERR_UNKNOWN otherwise, but I am not wedded to this.