[MPI3 Fortran] MPI-2 Fortran question: 2D char array in MPI_COMM_SPAWN_MULTIPLE

Bill Long longb at cray.com
Tue May 25 11:55:28 CDT 2010



Jeff Squyres wrote:
> A user recently reported to me a problem with the 2D character array in MPI_COMM_SPAWN_MULTIPLE in Open MPI.  Can you Fortran experts help me in what is supposed to happen?  
> 
> The MPI-2.2 binding for MPI_COMM_SPAWN_MULTIPLE in Fortran is as follows:
> 
> MPI_COMM_SPAWN_MULTIPLE(COUNT, ARRAY_OF_COMMANDS, ARRAY_OF_ARGV, ARRAY_OF_MAXPROCS,
>      ARRAY_OF_INFO, ROOT, COMM, INTERCOMM, ARRAY_OF_ERRCODES, IERROR)
> INTEGER COUNT, ARRAY_OF_INFO(*), ARRAY_OF_MAXPROCS(*), ROOT, COMM, INTERCOMM, ARRAY_OF_ERRCODES(*), IERROR 
> CHARACTER*(*) ARRAY_OF_COMMANDS(*), ARRAY_OF_ARGV(COUNT, *)
> 
> The ARRAY_OF_ARGV is the problem.
> 
> Notice that the user has to pass COUNT as the first INTEGER argument; so the MPI implementation knows the first dimension size of ARRAY_OF_ARGV.  

> The compiler passes the string length as an implicit last argument (or, at last the compilers do that we support in Open MPI).  

I would expect 2 such hidden arguments at the end of the argument list. 
  The first would be the length of each element of the array 
ARRAY_OF_COMMANDS and the second would be the length of each element of 
ARRAY_OF_ARGV.

Note that this convention of passing character argument lengths as 
hidden trailing arguments is a vendor implementation convention, but has 
no basis in the language standard.  Characters could also, for example, 
be passed as the address of a hidden struct, with the first member of 
the struct being the addresses of the beginning of the string, and the 
second the length.   If the interface specifies BIND(C) then an argument 
if character(1) has to be passed, essentially, as if it were an integer 
with the same number of bits, to match C convention.  Character 
variables with length > 1 are not interoperable, since there is no 
analog in C.



Take the following simplified/non-MPI example:
> 
>       program my_main
>       implicit none
>       character*20 argvs(2, 3)
> 
>       argvs(1, 1) = '1 2 3 4'
>       argvs(1, 2) = 'hello'
>       argvs(1, 3) = 'helloagain'
> 
>       argvs(2, 1) = '4 5 6 7'
>       argvs(2, 2) = 'goodbye'
>       argvs(2, 3) = 'goodbyeagain'
> 
>       call c_func(2, argvs)
>       end
> 
> And then I have a C function like this:
> 
> void c_func_backend(int *dim, char ***argvs, int string_len)
> { ... }
> 
> The MPI implementation needs 3 values:
> - length of each string (passed as string_len in this case: 20)
> - the first dimension size (passed as *dim in this case -- just like in MPI_COMM_SPAWN_MULTIPLE: 2)
> - the second dimension size
> 
> MPI doesn't have the 3rd value, so it has to calculate it.
> 
> Open MPI, LAM/MPI, and MPICH1/2 all calculate this value by doing something similar to the following:
> 
>   tmp = malloc(string_len + 1);
>   fill_tmp_with_spaces_and_null_terminate_it(tmp, string_len);
>   for (i = 0; 1; ++i) {
>       if (strcmp((*argv)[0] + i * (*dim) * string_len, tmp) == 0) {
>           second_dim_size = i;
>           break;
>       }
>   }
> 
> That is, they strategically look for a string_len sized string *comprised of all blanks* to denote the end of the array.

This would only work if the caller explicitly supplied such a value. 
And, as noted in a different email, the user also agrees to NOT allow 
any of the other values in the array to be all blanks.    The  user 
instructions on how to use the MPI function need to explicitly say that 
the user has to dimension the array one larger than needed and to insert 
the sentinel value by hand.


> 
> This heuristic has apparently worked for years.  But it is apparently not true in at least recent versions of gfortran -- recent gfortran does not seem to guarantee that the (1st_dim * 2nd_dim + 1)th entry is all blanks to denote the end of the array.
> 
> Craig Rasmussen is sitting next to me -- he doesn't think that this behavior is guaranteed by the Fortran spec.  
> 

Certainly a compiler would not automatically add in such an extra ending 
sentinel value.  If gfortran did this, someone probably filed a bug and 
had then fix it.  It would be possible, for example,  to have the actual 
argument be in a common block, followed by another character variable in 
the same common block, making the inclusion of an extra pad element in 
the array illegal.




> My question to you: what is the Right way for an MPI implementation to know how to find the end of the ARRAY_OF_ARGVS array?  

It would be cleaner to require that the user supply the second dimension 
as another argument.


Or is the MPI-2 binding for MPI_COMM_SPAWN_MULTIPLE incorrect?

It is incorrect if it fails to mention that the user is required to 
over-size the array and supply the sentinel value and also make sure 
that no other element of the array is the sentinel value.

Cheers,
Bill



> 
> Thanks!
> 

-- 
Bill Long                                           longb at cray.com
Fortran Technical Support    &                 voice: 651-605-9024
Bioinformatics Software Development            fax:   651-605-9142
Cray Inc./Cray Plaza, Suite 210/380 Jackson St./St. Paul, MN 55101





More information about the mpiwg-fortran mailing list