forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

forall index variables
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
IanLambley



Joined: 17 Dec 2006
Posts: 514
Location: Sunderland

PostPosted: Thu Jan 17, 2013 1:20 pm    Post subject: Reply with quote

David, being an oldie, I hardly ever if at all use a forall statement. However, I have just created a slightly different version of your program where the outer do loop variable is used as an array index.
Code:

program main

   integer i
   real b(5,2)
   real :: a(5) = (/1.0, 2.0, 3.0, 4.0, 5.0/)

   b = 0.0

   ! Should be able to nest forall inside do loop and use same index variable
   do j=1,2
     
      ! forall doesn't change defined/undefined status (or value if defined) of i
      forall(i=1:5)
         b(i,j) = b(i,j) + a(i)
      end forall
     
   end do
   
   ! should print 3
   print *, i

   ! should print 2.0, 4.0, 6.0, ...
   print *, b

end program main

Note this is hypothetical and not intended to give the same result as yours. I have changed the do loop variable to j to differentiate it from the i of the forall construct, but I think that this is a perfectly valid program structure that may be required. If the do loop index remained as i, then there would be a conflict just as in any other nested do loops.

The error provided by FTN95 is therefore perfectly reasonable, but feel free to shout at me if you wish.

Ian
Back to top
View user's profile Send private message Send e-mail
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2428
Location: Yateley, Hants, UK

PostPosted: Thu Jan 17, 2013 3:25 pm    Post subject: Reply with quote

Ian,

You are an oldie, just like me. The critical thing (pointed out by David) is that FORALL is not a loop construct, it is a parallel assignment. Hence, it is like the array assignment:

Code:
      DIMENSION A(5), B(5), C(5)
      A = B + C


Now, you or I could write that in a loop:

Code:
     DO 10 I=1,5
     A(I) = B(I) + C(I)
  10   CONTINUE


and we would be happy to do so. We would also know that at the end of the loop, I would be undefined, and on the basis of experience and a number of compilers, we would know that I was perhaps 5, or more probably 0, or perhaps even -1. Whatever, we would know that the loop messed around with the value of I. What we would be absolutely sure of is that I would not contain any value it had before the loop was entered, except by chance.

The rules are different for FORALL, and different to any Fortran construct you ever came across up to Fortran-77. The I in a FORALL is not the same as a variable of the same name elsewhere in the (sub)program unit: it is a new variable whose scope is local to the FORALL. Essentially, FORALL is a potential subset operation on an array assignment, so that one might have (for example) a couple of FORALLs so that even and odd I values might be B+C or B-C etc.

I will never use a FORALL, as the modification of the scoping rules upsets my view of what is correct and proper. David points out that the FORALL construct hints at the potential for parallelisation, but this is only possible if the FORALL is PURE (i.e. has no side effects). In the loop example above, that would be pure, but

Code:
     DO 10 I=1,5
     A(I) = A(I-1) + B(I) + C(I)
  10   CONTINUE


perhaps isn't (showing my ignorance here!) and if done using a FORALL instead of a DO, might conceivably give a different answer. It seems to me from the earlier discussion that a FORALL that used I-1 ought to use A(I-1) on entry to the FORALL, whereas a DO should use the A(I-1) from the previous loop step.

An implicit DO loop in a READ or WRITE statement follows what I consider to be classic scoping rules, and therefore has the effect I am used to. Mind you, Fortran 90 et seq. has interfered with the scoping rules through MODULE and CONTAINS to such an extent that all the old certainties have gone, unless one either embraces the new paradigm wholeheartedly or steadfastly refuses to have anything to do with it.

Eddie
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Thu Jan 17, 2013 7:51 pm    Post subject: Re: Reply with quote

IanLambley wrote:

the error provided by FTN95 is therefore perfectly reasonable, but feel free to shout at me if you wish.


There is no error in the original program I posted though. Very Happy It is not perfectly reasonable for a compiler that claims to be compatible with Fortran 95 to issue an error in this case.

Its a bug in the compiler and I hope it can be fixed in due course. There may be an underlying issue with FORALL indices scope as well, which I have made Paul aware of in another thread, and I am sure he will give it some attention, but I expect he has other fish to fry at the moment (64 bit stuff, etc.)

It doesn't help thinking about FORALL as a loop. As Eddie says above, it is really a more general form of array assignment. The indices are there to illustrate what gets assigned.

Its not even close to being a loop. If you run the following program you will see the forall and the do loop give completely different results.

Code:

program shuffle

   real a(5)

   a = (/(real(i), i=1,5)/)
   
   ! forall assignment

   forall(i=1:4)
      a(i+1) = a(i)
   end forall
     
   print *, a

   a = (/(real(i), i=1,5)/)

  ! do loop

   do i=1,4
      a(i+1) = a(i)
   end do
   
   print *, a

end program shuffle


As I said, array assignment and FORALL is really only a hint to the compiler that something can be parallelised (i.e. SIMD parallelisation). An optimizing compilers can sometimes figure this out from a DO loop though, but the FORALL makes this easier.

There are other developments going on in Fortran 2008, such as DO CONCURRENT which really is a loop, and would be more suited to SPMD parallelisation.

In my codes (some work, some hobby stuff) I make extensive use of SPMD (using OpenMP) and SIMD parallelisation and I find I use FORALL quite a lot. I also find that codes I have to maintain also use (or misuse sometimes) FORALL, so others are using it and it is something I need to know about.

There's a lot of new things in Fortran these days. You don't have to use them, however. But a good compiler (which FTN95 definitely is) needs to support as many of the new things it can to encourage "new adopters of Fortran" as well as keeping us "oldies" happy.

I hope in a small way my reports here on "corner cases" will help to improve FTN95 over time.
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl


Last edited by davidb on Thu Jan 17, 2013 8:14 pm; edited 1 time in total
Back to top
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2428
Location: Yateley, Hants, UK

PostPosted: Thu Jan 17, 2013 8:09 pm    Post subject: Reply with quote

David,

I'm not the authority on what FORALL is or does - I rely on your knowledge here!

Having thought about it (a lot) I can maybe see a possible benefit of it. But the scoping rules for many of the things in Fortran-90 break what I consider to be sacrosanct rules, and seem to me to have the potential to cripple my ability to see certain types of bugs "at a glance".

Most of my programming life has been done with subset compilers, and I have no difficulty with the subset of FTN95 that I use being not even the whole of FTN77! Just so long as it has Clearwin+

Do you get the same behaviour with .NET?

Eddie
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Thu Jan 17, 2013 8:21 pm    Post subject: Reply with quote

Good evening Eddie. How is the snow there Smile

When you use a Statement Function in Fortran 77 the arguments have a scope that is different to the scope of the containing function. Well, the use of a separate scope for forall is similar. What are the other Fortran 90 scoping rules you mentioned that "break the rules"? Can you give an example?

When programming in Fortran I find the best approach is to stick with the parts of the language I know very well. FORALL happens to be one of those areas for me, but I accept its a personal choice.

I have not tried compiling under .NET. I don't use it much.
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Back to top
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2428
Location: Yateley, Hants, UK

PostPosted: Thu Jan 17, 2013 8:45 pm    Post subject: Reply with quote

David,

It never snows much in the south of England, despite being at an Alaskan latitude. There were a few flakes today, and some on Monday. I cleaned my snow chains, and checked them for length on the car, but I haven't fitted them to my last 3 cars ....

A statement function is a horrible construct. But it is a function, and therefore has its own scope. Most people reading an old Fortran program don't understand statement functions. Consider the following:

Code:
      SUBROUTINE SAMPLE
      DIMENSION A(5), B(5), C(5)
      D(I) = A(I) + B(I) + C(I)
      ... etc
      END


You can't declare D as an array, as the name has a scope withing SAMPLE of being a FUNCTION. You can't alter I, which picks up the current value of I from wherever D is called. I suppose D must also be a PURE function.

It would be the same if SAMPLE CONTAINS 'FUNCTION D(I)', but expressed that way, D would have access to all variables in SAMPLE, e.g. A, B and C, and could alter any of them, as it is not required that D is PURE if it is CONTAINSed. I suppose the scope of A, B and C is still limited to SAMPLE, but for me it seems wrong somehow that D could have access to variables not passed via parameters or in COMMON and without explicit reference somewhere. A statement function is compelled by its own limitations to be PURE.

I have only ever used 3 statement functions. 2 of them map real world coordinates to screen coordinates, and never give me a problem. The other one always catches me out when I look at the code it is in, which is about once every 6 or 7 years ... I wish the statement function allowed me to declare it as one, i.e. STATEMENT FUNCTION D(I) = etc - but then a suitable comment helps (especially now they can be in-line).

Eddie
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Thu Jan 17, 2013 9:04 pm    Post subject: Reply with quote

You are correct to say that a statement function acts as if it is PURE. But this is a happy accident that is forced by the function being restricted to one line. The notion of a PURE function wasn't introduced in the language when Statement functions were invented.

You can write your one line example as a PURE function using CONTAINS if you want. This gives you a more explicit syntax and an explicit interface (and the ability to use more than 1 line).

Code:

      SUBROUTINE SAMPLE
      DIMENSION A(5), B(5), C(5)

      ... etc

      CONTAINS
           PURE FUNCTION D(I)
               D = A(I) + B(I) + C(I)
           END FUNCTION D
      END


This function access A, B and C using "Host association". The local variables in the main program can be accessed but cannot be changed.

Your statement function is doing exactly the same thing. Wink

Note that a function can still be PURE and read variables outside the scope of the program (host scope, module scope, common) but it can't write to any of these values (or write to disc, screen etc).

PS. In the DO i=1,5 loop you posted earlier, I always has the value 6 on exit from the loop. Smile It won't be 5 or 0 or -1.
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl


Last edited by davidb on Thu Jan 17, 2013 9:40 pm; edited 3 times in total
Back to top
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2428
Location: Yateley, Hants, UK

PostPosted: Thu Jan 17, 2013 9:16 pm    Post subject: Reply with quote

David,

Until I used Clearwin, I was unaware that functions could be anything other than PURE - as all the books (McCracken etc) always gave dire warnings of what might happen if you were daft enough to try. For decades it never occurred to me that parameters for a function could be anything other than INTENT IN (although for a subroutine they were definitely INOUT). Moreover, due to stack limitations, one always used COMMON in preference anyway, and COMMON is decidedly INOUT.

And quite definitely, a compiler should conform to standards.

Eddie
Back to top
View user's profile Send private message
IanLambley



Joined: 17 Dec 2006
Posts: 514
Location: Sunderland

PostPosted: Fri Jan 18, 2013 11:24 am    Post subject: Reply with quote

Sorry - that seemed to be like lobbing in a hand grenade and standing back.
All I was asking was how do you use a FORALL construct with arrays which have a rank greater than 1. Do all the subscripts have to be addressed by the FORALL ranges or can they be addressed by means external to the FORALL construct?
Ian
Back to top
View user's profile Send private message Send e-mail
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2428
Location: Yateley, Hants, UK

PostPosted: Fri Jan 18, 2013 3:14 pm    Post subject: Reply with quote

Ian,

I think it is an interesting discussion, as the concept of PURE has always been around but it is articulated only in the later standards. What happens if you declare a subprogram to be PURE, and it isn't? I think I might give it a go in the spirit of enquiry espoused by David.

You should be able to mix all constructs, unless the standard says you can't. The problem seems to me that if you mix DO and FORALL, you might not get the answer you expected with experience of nested DOs, and you probably won't with nested FORALLs - if they are a fancy assignment and not an alternative loop.

And David, as the loop variable is undefined on normal exit from a loop, then I never relied on it being anything unless I jumped out of a loop, at which time it retained its inside-the-loop value. I didn't believe then (c. 1979) that the loop variable could be anything other than 5 or maybe 6, so I tried it. But it was a long time ago when I had access to a big range of mainframes via cards or terminal input. It was never reliable, and yes, sometimes it was -1 or 0 on exit. Why, I never understood. With the benefit of hindsight, I ought to have tried it when I had a dozen different 16 bit compilers, but although I do have Absoft 32 bit, I've never been able to use it properly, and as far as G95 or even FTN95 for .NET is concerned, my lack of Klingon means that I can't seem to get past the installation instructions .... If FTN95 gives last value + 1 on loop exit, you shouldn't rely on it.

Eddie
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Fri Jan 18, 2013 5:26 pm    Post subject: Re: Reply with quote

Ian,

IanLambley wrote:
Sorry - that seemed to be like lobbing in a hand grenade and standing back.
All I was asking was how do you use a FORALL construct with arrays which have a rank greater than 1. Do all the subscripts have to be addressed by the FORALL ranges or can they be addressed by means external to the FORALL construct?
Ian


No problem.

You can mix DO and FORALL provided that FORALL is inside DO (You can't have DO inside FORALL). The code you posted is OK. So you can write code like the following:

Code:

   DO j=1, N
      FORALL(i=1:M)
         A(i) = B(i) + C(i,j)
      END FORALL
   END DO


When you do this, the J variable has the scope of the program unit (subroutine etc), and the I variable has its own FORALL scope. The FORALL statement is allowed to access J in the surrounding scope provided it doesn't change its value (making the expression PURE).

You can also do this using only FORALL in two ways:

Code:

   FORALL(j=1:N)
      FORALL(i=1:M)
         A(i) = B(i) + C(i,j)
      END FORALL
   END FORALL


or

Code:

   FORALL(i=1:M, j=1:N)
        A(i) = B(i) + C(i,j)
   END FORALL

_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl


Last edited by davidb on Fri Jan 18, 2013 5:54 pm; edited 1 time in total
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Fri Jan 18, 2013 5:42 pm    Post subject: Re: Reply with quote

Eddie,

LitusSaxonicum wrote:

What happens if you declare a subprogram to be PURE, and it isn't?


You will get a compiler error.

LitusSaxonicum wrote:

The problem seems to me that if you mix DO and FORALL, you might not get the answer you expected with experience of nested DOs, and you probably won't with nested FORALLs - if they are a fancy assignment and not an alternative loop.


That's true. You need to build up some experience using the FORALL syntax. It is different to DOs. If you don't learn how to use it properly, or think they are loops, you could get incorrect results.

LitusSaxonicum wrote:

And David, as the loop variable is undefined on normal exit from a loop, then I never relied on it being anything unless I jumped out of a loop, at which time it retained its inside-the-loop value.


If a loop is exited (using GOTO or EXIT) the value of the index retains its value outside the loop. If the DO loop runs to completion, the index is defined and has a value that is the first value in the counting sequence that exeeds the final value. e.g.

with DO I=1,5 then I = 6 after the loop (counting sequence 1,2,3,4,5,6)
with DO I=1,5,2 then I = 7 after the loop (counting sequence 1,3,5,7)
with DO I=1,6,2 then I = 7 after the loop (counting sequence 1,3,5,7)
with DO I=4,4 then I = 5 after the loop (counting sequence 4,5)
with DO I=4,2 then I = 4 after the loop (no counting, loop isn't executed)

In the most usual case, where the stride is 1, the final value is the count + 1.

This is standard Fortran 77 behaviour so has been around since 1978. (It was different in Fortan 66). The only caveat is that REAL indices are allowed in Fortran 77 and there could be some rounding problems, whereas they have to be integers since Fortran 95.

Most of the time I don't use the value of I after the loop, but sometimes it can be tested to see if a break out of the loop occurred or if the loop ran to completion. e.g.

Code:

DO I=1, N
   ...
   IF (...) EXIT
END DO
IF (I <= N) THEN
    ! A jump out occurred.
    ...
END IF


If you don't test I, you have to check for jump out as follows

Code:

JUMP = .FALSE.
DO I=1, N
   ...
   IF (...) THEN
      JUMP = .TRUE.
      EXIT
   ENDIF
END DO
IF (JUMP) THEN
    ! A jump out occurred.
    ! Eddie allows I to be used
    ...
END IF

_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Back to top
View user's profile Send private message
IanLambley



Joined: 17 Dec 2006
Posts: 514
Location: Sunderland

PostPosted: Fri Jan 18, 2013 9:15 pm    Post subject: Reply with quote

David,
Thanks that explains things, regarding multiple subscripts.
Regarding your first example, the do loop variable "I" must therefore only have scope outside the FORALL and the FORALL variable "I" only has scope within the FORALL and if there is a conflict of variables the within the statements, the FORALL takes precedence and can be regarded as a separate variable.
Perhaps, ensuring that it does not clash would give clarity and ensure that the do loop variable was accessible within the FORALL construct if necessary.

Otherwise the old folk like myself would be confused.
Ian
Back to top
View user's profile Send private message Send e-mail
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Fri Jan 18, 2013 10:11 pm    Post subject: Re: Reply with quote

IanLambley wrote:
David,
Thanks that explains things, regarding multiple subscripts.
Regarding your first example, the do loop variable "I" must therefore only have scope outside the FORALL and the FORALL variable "I" only has scope within the FORALL and if there is a conflict of variables the within the statements, the FORALL takes precedence and can be regarded as a separate variable.


Exactly so. In this case the DO Loop I variable cannot be seen inside the FORALL because it is obscured by the FORALL I variable which takes precedence.

IanLambley wrote:

Perhaps, ensuring that it does not clash would give clarity and ensure that the do loop variable was accessible within the FORALL construct if necessary.
Ian


Agreed. I would never use the construct given in the first example. I would always use different variable names. The example was provided just to illustrate a bug in the compiler.
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl


Last edited by davidb on Sat Jan 19, 2013 9:48 am; edited 2 times in total
Back to top
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2428
Location: Yateley, Hants, UK

PostPosted: Fri Jan 18, 2013 10:13 pm    Post subject: Reply with quote

Quote:
(It was different in Fortran 66)


I can't remember which compiler gave what behaviour, but I do remember that the first Fortran-77 compiler I used was on a VAX, and we didn't buy that until the 80s. Even when I got a PC, some of the compilers were still Fortran-66. It just shows that you have to (re-)question everything. I'm never going to rely on the exit value, though!

Eddie
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group