From: Om on
Hi,

Do O1,2,3 optimizations affect the way volatile variables are handled
in ifort 11.x ? For me the output of the following code is different
for different optimization levels. Here I am putting a skeleton
version.

I am using volatile variables for controlling two threads (created
using fortran-to-c interfaces) as follows :
================
common /counters/ i(2)
volatile i
i(2)=0
i(1)=0
........ create threads
do 55 while(i(2)==0) ! i(2) is set to 1 by other thread
55 continue
........
some computation
================
I am using volatile variables because otherwise program may not
evaluate (i2==0) every time in the loop.

However gfortran produces correct output every time.

Any help would be highly appreciated !
From: steve on
On Apr 29, 11:15 am, Om <helioph...(a)gmail.com> wrote:
> Hi,
>
> Do O1,2,3 optimizations affect the way volatile variables are handled
> in ifort 11.x ? For me the output of the following code is different
> for different optimization levels. Here I am putting a skeleton
> version.
>
> I am using volatile variables for controlling two threads (created
> using fortran-to-c interfaces) as follows :
> ================
> common /counters/ i(2)
> volatile i
> i(2)=0
> i(1)=0
> ....... create threads
> do 55 while(i(2)==0)   ! i(2) is set to 1 by other thread
> 55 continue
> .......
> some computation
> ================
> I am using volatile variables because otherwise program may not
> evaluate (i2==0) every time in the loop.
>
> However gfortran produces correct output every time.
>
> Any help would be highly appreciated !

Try removing the WHILE with

DO 55
IF (.NOT. (i(2) == 0)) EXIT ! Equivalent to your WHILE
....
55 CONTINUE

Looks like it might be a bug in Intel Fortran, but without a
full self-contained test case, so can only guess.

--
steve
From: JB on
On 2010-04-29, Om <heliophile(a)gmail.com> wrote:
> I am using volatile variables for controlling two threads (created
> using fortran-to-c interfaces) as follows :
>================
> common /counters/ i(2)
> volatile i
> i(2)=0
> i(1)=0
> ....... create threads
> do 55 while(i(2)==0) ! i(2) is set to 1 by other thread
> 55 continue
> .......
> some computation
>================
> I am using volatile variables because otherwise program may not
> evaluate (i2==0) every time in the loop.

Note that volatile in F2003 (and C99 and C++98 as well) does not
guarantee the semantics needed for volatile variables to be used as
synchronization primitives for mutual exclusion in the general
case. Also note that the contrary view, while wrong, is depressingly
common.

For instance, consider the following slight modification of your code:

! i is shared among both threads
common /counters/ i(2)
volatile i
integer :: priv ! Private variable in each thread
i(2) = 0
i(1) = 0
....... create threads
! Thread 1 |! Thread 2 |
i(1) = 1 | i(2) = 1 |
priv = i(2) | priv = i(1) |

Now, simple intuition tells us that at this point the value of "priv"
in both threads is either (1, 1), (0, 1) or (1, 0) depending on the
order in which the threads were executed. However, real life isn't
quite that simple, and on most architectures today, including
x86(-64), a fourth option is possible, namely (0, 0).

The solution is to use the concurrency primitives provided by the
platform, which are (hopefully) made by people who understand the
memory consistency model that the target hardware implements. On Linux
or other POSIX platforms, this is provided as part of the pthreads
library.

Even so, there are (somewhat rare, but still) cases where the compiler
might get things wrong. Luckily this situation is improving, due to
the memory consistency model defined in C++0x and C1X, and at least
the GCC optimizers are currently being audited for conformance.

--
JB
From: Jim Xia on

> > Do O1,2,3 optimizations affect the way volatile variables are handled
> > in ifort 11.x ? For me the output of the following code is different
> > for different optimization levels. Here I am putting a skeleton
> > version.
>
> > I am using volatile variables for controlling two threads (created
> > using fortran-to-c interfaces) as follows :
> > ================
> > common /counters/ i(2)
> > volatile i
> > i(2)=0
> > i(1)=0
> > ....... create threads
> > do 55 while(i(2)==0)   ! i(2) is set to 1 by other thread
> > 55 continue
> > .......
> > some computation
> > ================
> > I am using volatile variables because otherwise program may not
> > evaluate (i2==0) every time in the loop.
>
> > However gfortran produces correct output every time.
>
> > Any help would be highly appreciated !
>
> Try removing the WHILE with
>
> DO 55
>    IF (.NOT. (i(2) == 0)) EXIT  ! Equivalent to your WHILE
>    ....
> 55 CONTINUE
>
> Looks like it might be a bug in Intel Fortran, but without a
> full self-contained test case, so can only guess.


My guess is this code change would work. However you may argue with
compiler writer forever on whose fault it is for not having the
original code working.

The fact is Fortran volatile doesn't have the semantics you think it
has. Not all members on the standard body ever agreed on the
semantics of volatile variables. So if can, avoid using volatile
altogether. For the code Om has shown, it's likely the "do
while(i(2)==0)" has i(2) stuck with a register value and never got a
chance to be flushed. Fortran never clearly says whether this is
supposed to work or not.


Cheers,

Jim
From: Jim Xia on


> It maybe never says "clearly" what volatile means, but it does say
>
> "NOTE 5.21
> The Fortran processor should use the most recent definition of a
> volatile object when a value is required. Likewise, it should make the
> most recent Fortran definition available...."

A note is just a note. You should know better :-)


>
> and in normative text it says
>
> "The VOLATILE attribute specifies that an object may be referenced,
> defined, or become undefined, by means not specified by the program."
>


Right. But what exactly does that sentence mean?


> I thought everybody understood that the processor should do the right
> thing and never keep a volatile variable in a register for "very
> long."  Common value preserving optimizations are basically forbidden
> in a "good faith bug free" implementation of volatile.
>


I doubt. I didn't do a research on this, but I suspect there are many
so-called "bugs" in C or C++ compilers on volatiles. Anyway, Om
should argue with Intel compiler developers on this to see what they
say.


> If V is a volatile variable, then an expression like
> V + 3.14 + V
> should have 2 loads for V.  What isn't specified is how many
> fracto-seconds there are between the loads.


That expression is completely different from "do while (i(2) == 0))".


>
> There's no way to specify in syntax or semantics what volatile
> is supposed to do.  The standard doesn't even require a processor
> to have memory; it can't specify the timing of memory references.
> But, what could the intent be other than to require the processor
> to refresh the values whenever they are referenced?


Yes and no. Can you tell me exactly how many times i(2) is referenced
in "do while(i(2) == 0))"?



>
> I think it's like I/O.  That also is loosely specified (a processor
> doesn't have to do any and if it does it's all processor dependent; what
> could be less specified?)  Yet I/O works pretty prortably because
> everybody understands it and wants it to work.
>


That's an interesting analogue I haven't though of. I'll think about
it :-)


Cheers,

Jim