replica nfl jerseysreplica nfl jerseyssoccer jerseyreplica nfl jerseys forums.silverfrost.com :: View topic - forall index variables
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 1, 2, 3  Next
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Thu Dec 27, 2012 11:15 am    Post subject: forall index variables Reply with quote

In FORALL assignment, using a forall statement, or a forall construct, the index variable or variables should retain the defined/undefined status (and value if defined) they have at the start of the statement when the forall assignment is completed.

So in the following code, if i is undefined at the start it is undefined at the end, and if i = 4 (say) at the start then i = 4 at the end.

Code:

integer i
...

forall(i=1:10)
   x(i) = ...
end forall


This seems to be treated correctly. Essentially the index variables have a different scope to the local ones. This "rule" means the following code, in which the forall is nested inside a DO loop with the same index, is perfectly legal.

Code:

program main

   integer i
   real b(5)
   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 i=1,2
     
      ! forall doesn't change defined/undefined status (or value if defined) of i
      forall(i=1:5)
         b(i) = b(i) + a(i)
      end forall
     
   end do
   
   ! should print 3
   print *, i

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

end program main


However, the compiler generates error 953 - i is already being used as a do (or implied do) index . If I make the compiler ignore the error using /IGNORE 953, the code compiles and prints the correct value for i of 3 (it works properly even with /CHECKMATE turned on). This means the compiler will do the correct thing if the error message can be subverted.

Can forall indices be eliminated from the check for error 953? I realise this is not an important bug, just something you might see how to address easily at some time in the future.

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


Last edited by davidb on Thu Dec 27, 2012 3:14 pm; edited 3 times in total
Back to top
View user's profile Send private message
LitusSaxonicum



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

PostPosted: Thu Dec 27, 2012 12:48 pm    Post subject: Reply with quote

David,

Where do you go to learn these things? I've been reading books on post-Fortran77 all the way since Metcalf & Reid's 'Fortran 8x Explained' (which was what it was called until the 80s decade was well and truly over) - and never understood the half of it. Mind you, I struggled for a long time with FORMATs when converting from Algol-60 back in 1969, so wrestling with things written in Klingon is nothing new!

The error message you refer to is near to what a Fortran oldie would expect - so perhaps it merits a Warning at least.

It always seemed to me that the standards in Fortran 90 et seq were specified by people who hated Fortran as it was. A huge amount of effort was expended in doing things a different way, rather than (say) providing a standard method of accessing graphics, or for interacting with users - things that are done well by Clearwin, and which are far more useful than multiple ways of defining the precision of a variable, or of doing DO loops.

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



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Thu Dec 27, 2012 1:24 pm    Post subject: Reply with quote

Hi Eddie.

Well I'm one of those people who like to study the different standards and then try things out on different compilers. For a good translation of the standard I use "The Fortran 2003 Handbook" but I also use one of Metcalf and Reids books plus the different documentation with the compilers. It helps that I have a good understanding of C++ as well, which helps to make a lot of the "concepts" a bit less alien. (I started out writing Fortran IV then Fortran 77 and Pascal in the 80s).

Forall was added to Fortran 95 to provide opportunities for a programmer to hint at vectorisation on a compiler/processor that supports it (using SSE3 for example). Silverfrost FTN95 processes a Forall sequentially as far as I know, so it looks like a loop. However, technically it isn't a loop, but a fancy assignment.

A lot of the new things added from Fortran 90 can seem a bit unecessary for the Fortran 77 programmer. However, generally, the features provide ways of doing things that are essential for writing correct Fortran programs of any complexity (e.g. Explicit interfaces and Modules).

To give a specific example, the introduction of Derived Types (and Classes in Fortran 2003) makes coding much easier. But it also means that array elements of larger types can be made to "persist" on multiple, different cache lines (avoiding "false sharing"), which can provide a boost to efficiency when processes which act on them are made to run on multiple processors (using OpenMP for example, or Fortran 2008 coarrays).
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8210
Location: Salford, UK

PostPosted: Fri Dec 28, 2012 10:46 am    Post subject: Reply with quote

David

Thanks for the bug report. I have logged it for investigation.
Back to top
View user's profile Send private message AIM Address
LitusSaxonicum



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

PostPosted: Tue Jan 01, 2013 6:10 pm    Post subject: Reply with quote

David,

Thanks for the explanation - most helpful. So it is a type of assignment statement, not a loop. A pity it looks a lot like a loop then. I've spent a bit of time trying to find out about it, and what I discover is that it doesn't seem to be any sort of improvement on a DO loop.

One answer at least to my general ignorance: FORALL isn't in Metcalf and Reid's 'Fortran 8X Explained'.

My last remark in the previous posting stands. Do you think that you are the first person to discover the bug because you are the first person to use FORALL in FTN95? (Or the first person to reuse the 'i' variable in that particular way?).

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



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Tue Jan 01, 2013 6:57 pm    Post subject: Re: Reply with quote

Eddie,

FORALL was only introduced in Fortran 95, so it wouldn't be in "Fortran 8x explained" or any book about Fortran 90. It was originally introduced in High Performance Fortran (HPF) and was then included in Fortran 95.

The FORALL construct looks like a loop, but the FORALL statement does not.

The following code to extract the diagonal of a matrix is an example of the FORALL statement (meaning: assign the diagonal elements of A to the DIAG array):
Code:

FORALL(i=1:10) DIAG(i) = A(i,i)

This cannot be done using array notation, DIAG(:)=A(:,:) since the left-hand side and right-hand side are not conformable (they have different shapes)

Another example of a FORALL statement is the following code which copies the diagonal to another array in reverse order:
Code:

FORALL(i=1:10) B(i) = DIAG(11-i)

This cannot be done using array notation, B(:) = DIAG(:), since there is not way to do the reversal.

The FORALL construct is just a way of simplifying two or more FORALL statements which have the same indices. The above two statements can therefore be combined into a FORALL construct:
Code:

FORALL(i=1:10) DIAG(i) = A(i,i)
FORALL(i=1:10) B(i) = DIAG(11-i)

is the same as
Code:

FORALL(i=1:10)
   DIAG(i) = A(i,i)
   B(i) = DIAG(11-i)
END FORALL


It is important to note that first line inside the construct sets up ALL of the values of DIAG (for i=1:10), then the second line copies the values of DIAG to B in the reverse order.

This is definitely not the same as the following DO loop, which is incorrect code, since DIAG(11-i) is not defined on the first 5 passes.

Code:

DO i=1, 10
   DIAG(i) = A(i,i)
   B(i) = DIAG(11-i)  ! Error, since DIAG(11-i) is undefined when i=1
END DO


Two DO loops are needed to do the same operations as the FORALL construct correctly:
Code:

DO i=1, 10
   DIAG(i) = A(i,i)
END DO
DO i=1, 10
   B(i) = DIAG(11-i)
END DO


I know a lot of Fortran programmers who use FORALL a lot.
The BUG I have found only came to light because I have been studying the scope of FORALL indices. I was looking specifically at how my different Fortran compilers (NAG, Intel, Silverfrost, Gfortran, Open64, Oracle, Absoft) handle these variables and checking for conformance with the standard.

David.
_________________
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: 2402
Location: Yateley, Hants, UK

PostPosted: Tue Jan 01, 2013 11:04 pm    Post subject: Reply with quote

David,

An interesting and helpful exposition. Thank you for going to the trouble of explaining it. The two DO loops are the way I would have tackled this problem.

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



Joined: 16 Feb 2006
Posts: 2615
Location: Sydney

PostPosted: Wed Jan 02, 2013 4:19 am    Post subject: Reply with quote

David,

I note your confidence with FORALL, but I would be more cautious.

FORALL(i=1:10)
DIAG(i) = A(i,i)
B(i) = DIAG(11-i)
END FORALL

With this construct, can you be sure that all compilers would process the first line completely before B(i) =... ?

Also, your statement: "I know a lot of Fortran programmers who use FORALL a lot. "
Unfortunately, I know few Fortran programmers and fewer of them know FORALL !

Best wishes for the new year and look forward to your comments in 2013.

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



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Wed Jan 02, 2013 8:54 am    Post subject: Re: Reply with quote

JohnCampbell wrote:

With this construct, can you be sure that all compilers would process the first line completely before B(i) =... ?


All Fortran 95 compilers should, otherwise it would be a serious bug.

The point of FORALL is that it expresses the parallelism and lack of loop carried dependencies to the programmer. If the following appears in code I am writing or maintaining, I know that DIAG is assigned completely before B.

Code:

FORALL(i=1:10)
   DIAG(i) = A(i,i)
   B(i) = DIAG(11-i)
END FORALL


However, with the following code, I might be tempted to fuse the loops together to get more efficiency (thereby introducing a bug).

Code:

DO i=1,10
   DIAG(i) = A(i,i)
END DO
DO i=1,10
   B(i) = DIAG(11-i)
END DO


Hmm ... how can one be sure an optimizing compiler won't fuse these two loops together anyway. Wink

Best wishes to all for 2013.
_________________
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: 2402
Location: Yateley, Hants, UK

PostPosted: Wed Jan 02, 2013 2:50 pm    Post subject: Reply with quote

David and John,

For a few years from early 1970 to about early 1974, if called upon to write code for this, I would probably have done the 2 do loops. After reading a slim tome by Kreitzberg & Schneiderman, I would have used just one loop to save the loop overhead:

Code:
      DO 100 I=1,10
      DIAG (I) = A (I, I)
      B (I)    = A (11-I, 11-I)
 100  CONTINUE


Back in the 70s, I was using non-optimising compilers, and so would probably have precalculated 11-I, especially if I was using it a number of times rather than just twice. After a while, I might have indexed B differently, realising that A(I,I) would only be fetched once even if referred to twice:

Code:

C...    Assumes that A is fully populated first
      DO 100 I=1,10
      DIAG (I) = A (I, I)
      B (11-I) = A (I, I)
 100  CONTINUE


On my first introduction to Fortran I was aghast at statement numbers: I was used to Algol-60's BEGIN ... END constructs, and used indenting to wander code across all 132 lineprinter columns. You got a sense of the flow of code in this way. I hated the 72 column business with its lack of space, and continuation codes in column 6. Eventually, I realised that a statement number is an 'outdent', and a DO loop with a statement number tells you where you are going before you get there! Moreover, since late 1983 I have had printers that only print 80 columns readably, and the lack of space became less critical, as I realised that I could only take in relatively simple formulae at a glance, or understand them decades (or even weeks!) after they were written. My Algol-60 codes had usually used much less than the 132 columns anyway by the time multi-level indenting was taken into account.

I'd go even further than John, and say that you, David, are the first Fortran programmer I have ever come across who even knew that FORALL existed, let alone used it and mastered it to the point of debating compile time errors (not that one comes across many Fortran programmers these days, particularly in the shed at the end of my garden).

In the early PC days, I collected compilers much as David does, but mainly used Microsoft's. It was something of a delight not to be stuck with just one compiler on any computer, as was the case in mainframe days (the CDC 6xxx series had MNF and FTN). The advantages of one were always offset by a disadvantage elsewhere. In the case of FTN95, having Clearwin is the trump card, but even in DBOS days, one had graphics, whole libraries of useful functions and primitive windowing - as well as the ability to access lots of RAM on a 386 or 486 (without which it wouldn't run anyway).

For this old dog, is FORALL really a new trick worth learning?

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



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Wed Jan 02, 2013 10:09 pm    Post subject: Reply with quote

Interesting points Eddie and John.

It's only worth it if you want or need the speed-up that vectorisation can bring and you are using a compiler that supports it. (4X double precision or 8X single precision, on the new processors which support AVX instructions.)

In the following code for in place LU factorisation, the FORALL version is about 8 times faster for moderate values of n (using the Intel compiler). Notice how most of the loops and overhead have disappeared from the FORALL version.

I doubt you would see much difference with FTN95 though.

Code:

subroutine lu_f77(a)
   integer i,j,k,n
   real a(n,n)
   do k = 1, n-1
      do i = k+1, n
         a(i, k) = a(i, k) / a(k, k)
      end do
      do i = k+1, n                 
         do j = k+1, n
            a(i, j) = a(i, j) - a(i, k)*a(k, j)
         end do
      end do
   end do
end subroutine lu_f77

subroutine lu_f95(a,n)
   integer i,j,k,n
   real a(n,n)
   do k = 1, n-1
      a(k+1:n, k) = a(k+1:n, k) / a(k, k)
      forall (i=k+1:n, j=k+1:n)
         a(i, j) = a(i, j) - a(i, k)*a(k, j)
      end forall
   end do     
end subroutine lu_f95


Since Fortran 95 must support both ways of doing things, I hope my bug report proves useful for Silverfrost to provide a compliant FORALL for the, possible minority, of programmers who utilise it (even if that minority is only me Smile).
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2615
Location: Sydney

PostPosted: Wed Jan 02, 2013 11:04 pm    Post subject: Reply with quote

David and Eddie,

An interesting twist to the tale of FORALL is that Salford FTN95 had some bugs with it's implementation of FORALL for a number of years. As a consequence I have been slow to use it's syntax.
My impression is that FORALL was implemented in Fortran 95 as a pseudo "parallel" code syntax, but few compilers provided any efficiency gains from it. Even today, other optimising compilers do not automatically parallelise FORALL structures, or show any performance benefits over DO codings for the same compiler options.

FORALL has the important restriction in that the code must be "pure" and the order of calculation can not be assumed, which the compiler is to use when optimising.

Most FORALL can be easily replaced by a 1-line DO loop, such as:
DO I=1,10 ; DIAG (I) = A (I, I) ; END DO

It can be an elegent syntax, but provides little practical benefit over DO.

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



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Thu Jan 03, 2013 8:55 am    Post subject: Reply with quote

Sometimes FORALL is clearer code.

Look at these ways of shuffling the contents of an array. The FORALL is much clearer and closer to the mathematical syntax; the DO loop needs to work sequentially in reverse order.

Code:

program shuffle

   real a(5)

   ! Shuffle with forall   
   a = (/(real(i), i=1,5)/)
   
   forall(i=1:4) a(i+1) = a(i)
     
   print *, a

   ! Incorrect implementation of shuffle with do
   a = (/(real(i), i=1,5)/)

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

   ! Correct shuffle with do (need to go backwards!!!)
   a = (/(real(i), i=1,5)/)
   
   do i=4,1,-1
      a(i+1) = a(i)
   end do
   
   print *, a

end program shuffle

_________________
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: 2402
Location: Yateley, Hants, UK

PostPosted: Thu Jan 03, 2013 9:30 pm    Post subject: Reply with quote

Several points from this discussion, firstly that a compiler ought to conform to the standard, even if it seems to anyone that the particular facility in a standard is pointless. David's findings are therefore of great use.

Secondly, the standard doesn't say anything about 'warnings', and these can be as helpful as possible to the majority of users (FTN95 scores well here). But, the 'errors' should be 'standard conforming'.

Thirdly, FORALL doesn't actually do anything that you can't do in a DO loop - all these discussions end up by showing how the DO loop would look like. Sometimes, the DO loop(s) are a bit contrived. A useful comment that the loop needs to be 'PURE'. I always believed that FUNCTIONs should be 'pure', but some programming styles lead to 'impure' functions, and I suspect that the changes in scoping rules with MODULEs makes it more likely that routines will not be 'PURE'. I would concede that there will be cases where 90 and 95 constructs might be more elegant than 77 constructs, but I have yet to encounter a situation in my own programming that needs them.

As well as missing the opportunity to add graphics and GUI facilities to Fortran, the Standard Committee could have made in incumbent on compiler writers to generate the most efficient code ...

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



Joined: 16 Feb 2006
Posts: 2615
Location: Sydney

PostPosted: Fri Jan 04, 2013 12:47 am    Post subject: Reply with quote

Eddie,

Your points are well made.
However F77 had its problems. F90 standard was a significant improvement, although I regret that I did not provide input into the standard committee when it was being developed.
The standard committee has lacked the input from Fortran users, being more dominated by compiler developers and computer scientists who use other languages.
F77 had a number of poor compromises and lack of definition, due to operating system limitations of (a) major hardware manufacturer.
There was discussion in 1980's that a significant source of coding errors could be addressed by improving the linking process, but like GUI, none of this became included in the standard. The complexity of KIND is typical of how to make something simple more complex. It implies you can "adjust" the precision, when there are very few hardware options available. REAL*8 is much more effective for a programmer, but never got to the main table.
Post F95, Fortran has been taken over by C programmers, with most of the effort to turn Fortran into C, but little attention to improving the needs of numerical calculations.
Improved functionality for ALLOCATE has not happened, nor has addressing GUI's or the linking process.
We now have inter-operability and more obscure allocated derived types, few of which are needed for FORmula TRANslation computations. I wrote indexed list structures back in 70's and do not see any great leap forward with F2008. All I see is a standard that is so complex, that few compiler developers would be able to pay for developing a stable conforming compiler.
While I might dismiss your holding on to F77, I am exactly the same as you as I hold onto F95.

Unfortunately, the code committee has long dismissed us programmers and our comments and persists with a new Fortran version of C that fewer require. Any improvements are coming from compiler developers and hardware, such as Checkmate from FTN95 and OpenMP for parallel computation, outside the standard. F90 was developed with the intention of improving portability, which is an aim that is being forgotten.

My apologies David, if these old views differ from your experience, but we must all embrace the diversity.

Thanks for your discussions in 2012 and I look forward to your comments and assistance in 2013,

John
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 1, 2, 3  Next
Page 1 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