Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
jeffhammond opened this issue Nov 9, 2015 · 10 comments
Open

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

jeffhammond opened this issue Nov 9, 2015 · 10 comments

Comments

@jeffhammond
Copy link
Owner

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
Copy link
Owner Author

@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
Copy link
Owner Author

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
Copy link
Owner Author

@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:

  • MPI_COMMAND_ARGUMENT_COUNT
  • MPI_GET_COMMAND_ARGUMENT_LEN (routine name length is 28 character)
  • MPI_GET_COMMAND_ARGUMENT

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
Copy link
Owner Author

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
Copy link
Owner Author

@RolfRabenseifner said:

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

INTEGER, INTENT(INOUT) :: length

Is it

  • the returned string length, or
  • the original length of the command argument which may be truncated.

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

  • first calls the routine to detect the length of the argument,
  • second to malloc / allocate the appropriate string variable, and
  • third to call the routine again to read the command argument without any truncation.

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

  • A fixed maximum length, defined with an MPI constant, which itself may have a guaranteed minimum value.
  • A two routines interface, the first to inquire the length of the string that should be read, and the second interface to read the string.

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
Copy link
Owner Author

@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
Copy link
Owner Author

@jsquyres said:

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

@jeffhammond
Copy link
Owner Author

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
Copy link

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
Copy link
Owner Author

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants