From: michael on
The following function when called causes an access vioaltion error if
compiled with -O3 switch with the Intel Fortran 9.1 compiler. It works
ok if optimization is disabled. The offending statement is
IF(I1.LT.1)I1=1

DOUBLE PRECISION FUNCTION VSUM(V,N,I1,N)
IMPLICIT NONE
INTEGER I,I1,N
DOUBLE PRECISION V(N)
DOUBLE PRECISION ZERO
DATA ZERO/0.0D+0/

IF (N .LT. 1) RETURN
IF(I1 .LT. 1) I1=1

VSUM=ZERO
DO I=I1,I2
VSUM=VSUM+V(I)
ENDDO

RETURN
END

From: mecej4 on
michael(a)athenavisual.com wrote:
> The following function when called from a Main Program causes an access
> violation error if
> compiled with -O3 switch with the Intel Fortran 9.1 compiler. It works
> ok if optimization is disabled. The offending statement is
> IF(I1.LT.1)I1=1
>
> DOUBLE PRECISION FUNCTION VSUM(V,N,I1)
> IMPLICIT NONE
> INTEGER I,I1,N
> DOUBLE PRECISION V(N)
> DOUBLE PRECISION ZERO
> DATA ZERO/0.0D+0/
>
>
> IF (N .LT. 1) RETURN
> IF(I1 .LT. 1) I1=1
>
>
> VSUM=ZERO
> DO I=I1,N
> VSUM=VSUM+V(I)
> ENDDO
>
>
> RETURN
> END
>
The variable I1 is probably not initialized with a value before the
subroutine is called. Changing the optimization level can cause that
(leftover) value to be different.

-- mecej4
From: jon on

michael(a)athenavisual.com wrote:
> The following function when called from a Main Program causes an access
> violation error if
> compiled with -O3 switch with the Intel Fortran 9.1 compiler. It works
> ok if optimization is disabled. The offending statement is
> IF(I1.LT.1)I1=1
>
> DOUBLE PRECISION FUNCTION VSUM(V,N,I1)
> IMPLICIT NONE
> INTEGER I,I1,N
> DOUBLE PRECISION V(N)
> DOUBLE PRECISION ZERO
> DATA ZERO/0.0D+0/
>
>
> IF (N .LT. 1) RETURN
> IF(I1 .LT. 1) I1=1
>
>
> VSUM=ZERO
> DO I=I1,N
> VSUM=VSUM+V(I)
> ENDDO
>
>
> RETURN
> END

In Fortran 95, this function can be replaced with the SUM intrinsic
function.

Also, without using Fortran 95, you can't communicate the INTENT of the
dummy arguments. Maybe the O3 is "intent" on making the function have
no side effects, which in your case is assigning a new value to I1
before returning. In the spirit of the Fortran 77 used above (shudder)
you could try this, which might work:

DOUBLE PRECISION FUNCTION VSUM(V,N,I1)
IMPLICIT NONE
INTEGER I,I1,N
INTEGER I2
DOUBLE PRECISION V(N)
DOUBLE PRECISION ZERO
DATA ZERO/0.0D+0/

I2 = I1
IF (N .LT. 1) RETURN
IF(I2 .LT. 1) I2=1


VSUM=ZERO
DO I=I2,N
VSUM=VSUM+V(I)
ENDDO


RETURN
END

From: glen herrmannsfeldt on
jon <jon_d_r(a)msn.com> wrote:

(snip of program modifying I1)

> In Fortran 95, this function can be replaced with the SUM intrinsic
> function.

> Also, without using Fortran 95, you can't communicate the INTENT of the
> dummy arguments. Maybe the O3 is "intent" on making the function have
> no side effects, which in your case is assigning a new value to I1
> before returning. In the spirit of the Fortran 77 used above (shudder)
> you could try this, which might work:

If a constant was passed to I1 that could cause problems in
any Fortran 77 implementation. (Any version from Fortran I to 2003.)

> DOUBLE PRECISION FUNCTION VSUM(V,N,I1)
> IMPLICIT NONE
> INTEGER I,I1,N
> INTEGER I2
> DOUBLE PRECISION V(N)
> DOUBLE PRECISION ZERO
> DATA ZERO/0.0D+0/
>
> I2 = I1
> IF (N .LT. 1) RETURN
> IF(I2 .LT. 1) I2=1
>
> VSUM=ZERO
> DO I=I2,N
> VSUM=VSUM+V(I)
> ENDDO
>
> RETURN
> END

This would seem a good solution if the changed value of I1 isn't
needed. I would probably use:

DOUBLE PRECISION FUNCTION VSUM(V,N,I1)
IMPLICIT NONE
INTEGER I,I1,N
DOUBLE PRECISION V(N)
VSUM=0.D0
DO I=MAX(1,I1),N
VSUM=VSUM+V(I)
ENDDO
RETURN
END


Expressions in DO parameters are allowed.
I used to use constants like DATA ZERO/0.D0/ in Fortran 66 which
didn't allow expressions in I/O lists. There isn't much reason now.

DO loops with N<1 should be fast enough not to need the extra IF.

Note that yours doesn't initialize VSUM when N<1.
(I am not sure N is allowed less than 1 as an array dimension.)

-- glen
From: michael on
Thanks Glen:
This is a good tip. For all people who sent a response, the function
was not meant to replace the sum function in Fortran 95. It is an
example of things going wrong when you do high level optimization and
you don't write proper code.

I would be interested to hear Steve's opinion from Intel

Michael

glen herrmannsfeldt wrote:
> jon <jon_d_r(a)msn.com> wrote:
>
> (snip of program modifying I1)
>
> > In Fortran 95, this function can be replaced with the SUM intrinsic
> > function.
>
> > Also, without using Fortran 95, you can't communicate the INTENT of the
> > dummy arguments. Maybe the O3 is "intent" on making the function have
> > no side effects, which in your case is assigning a new value to I1
> > before returning. In the spirit of the Fortran 77 used above (shudder)
> > you could try this, which might work:
>
> If a constant was passed to I1 that could cause problems in
> any Fortran 77 implementation. (Any version from Fortran I to 2003.)
>
> > DOUBLE PRECISION FUNCTION VSUM(V,N,I1)
> > IMPLICIT NONE
> > INTEGER I,I1,N
> > INTEGER I2
> > DOUBLE PRECISION V(N)
> > DOUBLE PRECISION ZERO
> > DATA ZERO/0.0D+0/
> >
> > I2 = I1
> > IF (N .LT. 1) RETURN
> > IF(I2 .LT. 1) I2=1
> >
> > VSUM=ZERO
> > DO I=I2,N
> > VSUM=VSUM+V(I)
> > ENDDO
> >
> > RETURN
> > END
>
> This would seem a good solution if the changed value of I1 isn't
> needed. I would probably use:
>
> DOUBLE PRECISION FUNCTION VSUM(V,N,I1)
> IMPLICIT NONE
> INTEGER I,I1,N
> DOUBLE PRECISION V(N)
> VSUM=0.D0
> DO I=MAX(1,I1),N
> VSUM=VSUM+V(I)
> ENDDO
> RETURN
> END
>
>
> Expressions in DO parameters are allowed.
> I used to use constants like DATA ZERO/0.D0/ in Fortran 66 which
> didn't allow expressions in I/O lists. There isn't much reason now.
>
> DO loops with N<1 should be fast enough not to need the extra IF.
>
> Note that yours doesn't initialize VSUM when N<1.
> (I am not sure N is allowed less than 1 as an array dimension.)
>
> -- glen