There ARE some reasons to be concerned about compiler optimizations in
Fortran code which mixes with C code. A Fortran 77 compiler may assume
that it can RELIABLY determine which variables are potentially referenced
or modified across a call. In the absense of pointers, only globally
visible variables (COMMON areas) and actual parameters to the call are
exposed to the callee. Fortran passes its parameters by reference which
called C functions can treat as pointers. Any C function which exploits
this fact by keeping the pointer for later use in some function which
does not include that variable in its parameter list has done something
the Fortran compiler cannot understand.
Unfortunately, the function MPI_ADDRESS and its use in constructing
datatypes for use with MPI_BOTTOM can create similar problems by doing
what the Fortran compiler considers impossible. Once a Fortran
program calls MPI_ADDRESS(X,AX) and uses AX to construct a datatype
containing X, a call to MPI_SEND or MPI_RECV(MPI_BOTTOM,1,Xtype,...)
will expose X to be referenced or updated while the compiler may "know"
this cannot happen.
If a Fortran compiler has a "loc" function built into it then it should
understand that variables which have been passed to "loc" can no longer
be tracked across function calls with confidence. If "loc" is a utility
routine written in C and used in Fortran code then it can create the same
problems as MPI_ADDRESS.
Similar risks do not normally exist with a C compiler since the language
has pointers and the compiler understands that fact. To a C compiler, the
set of variables which are exposed across a function call are any
which are global and any which have been the subject of an "&" operator.
(For this discussion we can view a C array a[] as a nameless thing
known only by way of the pointer "a" which represents &nameless_thing.)
If a call is made to MPI_Isend from C, the compiler will assume that
all variables which are potentially visible to a function must be made
up to date in storage before the call. It will also assume that any
such variable referenced after return must be reloaded from storage
even if there was a copy in a register before the call. As long as the
rule about not touching a receive buffer between MPI_Isend and message
completion is followed there will be no problem with MPI-1 code in C.
========================================================================
int i,j,k;
/* create datatype "newtype" by using &i. Note that using MPI_Address as
urged by the standard will still involve &i, not i as the parameter. */
..
MPI_Rma_init(&i,1,MPI_INT,....);
..
i = 100; <-1->
..
/* Do long piece of work with may make use of "i" but does not change it.
The work does not make a function call. */
..
i++; <-2->
..
/* It is likely that the fact i==100 for a long while never shows in
storage but before the call,the new value of i(101) will be written. */
MPI_Isend(MPI_BOTTOM,1,newtype,...);
..
/* Wait on Isend, do not change i */
..
MPI_Irecv(MPI_BOTTOM,1.newtype,...);
j = i; <-3-> /* If we assume Irecv has not done it work yet, j = 101 */
..
/* do work which has no function calls but takes long enough for
Irecv to finish. */
..
k = i; <-4-> /* If i, loaded in a register for j = i, is still there, it will
likely be used even if the copy of i in storage has changed.*/
MPI_Wait(...);
k = i; /* i will be reloaded from storage because the compiler
understands that any function call can change i. */
========================================================================
The statements at <-3-> and <-4-> clearly violate the MPI-1 rules and
a program with such statements is user error. There is no need for
"volatile" declarations here unless you are doing something which
intensionally breaks MPI-1 rules.
The section from <-1-> to <-2-> under MPI-2 is another story. The
compiler will analyze the code in this range and determine that there
is no need put "a" in storage after <-1-> or to load it from storage
for the increment at <-2->. An MPI_Get of 'i' in this range will fail
to find the current value. An MPI_Put of 'i' will write the storage
copy of "i" and the register value of "i" will overwrite that at <-2->.
CONCLUSIONS:
1) A programmer who mixes Fortran and C must understand the assumptions
of Fortran optimization and avoid violating those assumptions in the
C code. There should be an acceptance of risk in deciding to mix but
it is not am MPI issue.
2) MPI-1 defined a function, MPI_ADDRESS, which can create the risk for
Fortran programmers who are unaware they are doing something akin to
using C subroutines.
3) C programs which obey the rule which says hands off the buffer between
an Isend/Irecv and its completion should not need to use "volatile" for
MPI-1. Fortran programs which obey the same rule and avoid MPI_ADDRESS
are likewise safe. Fortran programs should also be OK with only the
"hand off" rule as long as MPI_ADDRESS is used with data in COMMON. This
is because the compiler must assume that the MPI_WAIT call could reference
or modify any data in COMMON.
4) MPI-2 1-sided chapter will need to discuss the "volatile" concept.
Dick Treumann
Dick Treumann POWER Parallel Division
(Internet) treumann@kgn.ibm.com IBM -- Poughkeepsie, NY
(VNET) TREUMANN at KGNVMC Tel: (914) 433-7846
(internal) treumann@windsurf.kgn.ibm.com Fax: (914) 433-8363