[Mpi-comments] MPI 3.0: Fortran 2008 interface - issue with the LOGICAL kind

Jeff Squyres (jsquyres) jsquyres at cisco.com
Tue Feb 26 08:44:48 CST 2013


Thank you Tobias; this is an extremely detailed report -- it is most excellent.

I'm going to forward it to the Fortran working group (which you might want to join if you represent the Pathscale fortran group?): 

    http://lists.mpi-forum.org/mailman/listinfo.cgi/mpi3-fortran



On Feb 26, 2013, at 7:19 AM, Tobias Burnus <burnus at net-b.de> wrote:

> Dear all,
> 
> Digest version: The Fortran 2008 interface should use "LOGICAL(kind=C_BOOL)" instead of "LOGICAL".
> 
> 
> MPI 3 [1] adds a new Fortran 2008 interface (or rather one using Fortran 2008 [2] plus TS 29113 [3]), which uses C binding ("bind(C)"). For instance the following (from "6.7.2 Communicators"):
> 
> ABSTRACT INTERFACE
> SUBROUTINE MPI_Comm_copy_attr_function(oldcomm, comm_keyval, extra_state,
> attribute_val_in, attribute_val_out, flag, ierror) BIND(C)
> TYPE(MPI_Comm) :: oldcomm
> INTEGER :: comm_keyval, ierror
> INTEGER(KIND=MPI_ADDRESS_KIND) :: extra_state, attribute_val_in,
> attribute_val_out
> LOGICAL :: flag
> 
> 
> The code assumes that the default-kind INTEGER and LOGICAL are interoperable. It is very likely that default-kind integers are interoperable, given that C supports many integer types (signed char, short, int, long, long long) and that Fortran's default-kind integer typically matches "int".
> 
> 
> However, for LOGICAL this is not necessarily the case. Fortran's default-kind LOGICAL is always [5] as wide as the default-kind INTEGER ("LOGICAL(kind=4)"). However, C99's [4] _Bool is on nearly all systems (one exception is 32bit Darwin) only one byte wide (sizeof(_Bool) == 1) [6]. The Fortran standard only defines interoperability with this logical kind:
> 
> 
> Fortran 2008, "15.2.2 Named constants and derived types in the module": "The value of C_BOOL shall be a valid value for a logical kind parameter on the processor or shall be -1."
> 
> Fortran 2008, "Table 15.2: Interoperability between Fortran and C types":
> "Fortran type / Named constant from the ISO C BINDING module (kind type parameter if value is positive) / C type"
> ...
> "LOGICAL / C_BOOL / _Bool"
> 
> 
> Hence, a conforming compiler might only accept a single interoperable LOGICAL kind, namely: C_BOOL. That's actually the case for the PathScale/pathf95 compiler — and also GCC/gfortran (version >= 4.8) with -std=f2003/f2008/f2008ts only accepts LOGICAL(C_BOOL) but not LOGICAL [7].
> 
> 
> Note an additional potential issue: C99's _Bool only allows two values, 0 and 1; see C99's "6.3.1.2 Boolean type": "When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1."
> 
> At least the GCC makes use of this restriction and sets TYPE_PRECISION to 1 for C99/C++'s _Bool/bool and Fortran's LOGICAL (for all KIND= values). As the hardware typically supports instructions of the form "jump if zero" or "jump if not zero", also other values work in "if (bool_var)". However, for negation (C/C++: "!", Fortran: ".not."), GCC only flips one bit. Hence, for C99's _Bool, C++'s bool and Fortran's LOGICAL (any kind), negating "-2" leads to "-1".
> 
> Example: If you have in one file:
> "signed char bool_var = -2; sub(bool_var)"
> and in the other file either:
> void sub(_Bool bool_var)
> or
> subroutine sub(bool_var) bind(C)
> logical(kind=C_Bool), value :: bool_var
> both "bool_var" and "!bool_var"/".not.bool_var" evaluate to true/.true.
> 
> In that sense, Fortran's "LOGICAL :: v" is not interoperable with C's "int v" unless the value is restricted to 0 and 1.
> 
> Note regarding C99: If you assign or cast to _Bool, the compiler ensures that only the value 0 and 1 is used. Additionally, many operations in C99 return an "int", for instance "&&" or "||" do (see C99, "6.5.13 Logical AND operator" and 6.5.14). Thus, in pure C code one does not easily run into this issue. Nor in pure Fortran code as one there typically doesn't mix LOGICAL with INTEGER. But when mixing C and Fortran (or mixes code compiled iwth different compilers [8]), this can lead to wrong code.
> 
> 
> Hence, I strongly suggest to change in all BIND(C) procedures LOGICAL to LOGICAL(C_Bool). For the three reasons above: (a) the standard only defines interop with kind=C_Bool; (b) pathf95 [and gfortran with -std=f2008ts] only support C_Bool kind logicals with Bind(C); (c) at least with GCC, using default-kind LOGICAL might lead to wrong results if the value is not 0 or 1.
> 
> 
> Tobias
> 
> PS: The issue came up with Open MPI's bug report https://svn.open-mpi.org/trac/ompi/ticket/3523
> 
> 
> [1] MPI 3: http://www.mpi-forum.org/docs/mpi-3.0/mpi30-report.pdf; erratum http://www.mpi-forum.org/docs/errata-30.pdf
> [2] Fortran 2008 (FDIS): ftp://ftp.nag.co.uk/sc22wg5/N1801-N1850/N1830.pdf ; corrigenda 1 & 2: ftp://ftp.nag.co.uk/sc22wg5/N1901-N1950/N1903.pdf , ftp://ftp.nag.co.uk/sc22wg5/N1951-N2000/N1958.pdf
> [3] TS 29113 (FDIS): ftp://ftp.nag.co.uk/sc22wg5/N1901-N1950/N1942.pdf
> [4] C99+TC1,TC2,TC3: http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
> [5] That's required in Fortran 2008's "16.5.3.2 Storage sequence": "a nonpointer scalar object that is default integer, default real, or default logical occupies a single numeric storage unit,"
> [6] That _Bool has is one byte wide is implied by C99's "The rank of _Bool shall be less than the rank of all other standard integer types." (6.3.1.1), but in my reading it does not formally demand it. With GCC, one can force this width for 32bit Darwin via -mone-byte-bool.
> [7] Currently, GCC still accepts LOGICAL / LOGICAL(4) with default options (-std=gnu); however, that might change. See discussion at http://gcc.gnu.org/ml/fortran/2013-01/msg00090.html and http://gcc.gnu.org/PR55758
> [8] In particular, Intel's Fortran compiler uses "-1" for .true., independent of logical kind and bind(C); for the reasons outlined above, it thus interacts badly with GCC/gfortran.
> _______________________________________________
> mpi-comments mailing list
> mpi-comments at lists.mpi-forum.org
> http://lists.mpi-forum.org/mailman/listinfo.cgi/mpi-comments


-- 
Jeff Squyres
jsquyres at cisco.com
For corporate legal information go to: http://www.cisco.com/web/about/doing_business/legal/cri/





More information about the mpi-comments mailing list