levine@jadoube.mcs.anl.gov (10/26/89)
I've recently ported an existing Fortan 77 program to Fortran 8x and found what I consider significant limitations in the WHERE statement. The problems I've encountered stem from the WHERE statement being just a masked assignment statement, and not a parallel IF statement. So only array assignment statements are allowed in WHERE blocks. In particular other (nested) WHERE statements are not allowed nor are subroutine calls. At least for the example below, the 8x code seems awkward to write, and the amount of it required greater than the necessary 77 code. The code fragments are from a cellular automata program that implements a 2-d hexagonal lattice on an N by N array. The things in the 77 code that I think make the 8x port difficult are: 1) Nested IF statements 2) Dealing with boundary conditions in the same loop as dealing with the bulk. 3) The problem geometry( mapping a hexagon into a rectangle). The problems I see with the WHERE statement are the following: 1. The inability to nest WHERE statements leads to having to AND together all the logical expressions making the code a) larger b) difficult to read and c) more inefficient (all the repeated mask computations [maybe with some ugly kludge these can be precomputed but the code gets even uglier]). I consider the inability to nest WHERE statements a very serious limitation. 2. Also not allowed in WHERE statements are subroutine calls. It seems natural to want to make a subroutine call to make a calculation in some cases but not others. Short of inlining the subroutine, or passing the mask to the subroutine there doesn't seem to be a sensible way to do this. 3. There is no ELSEWHERE IF structure. By analogy with the IF statement IF WHERE : ELSEIF ! nothing analagous (i.e., ELSEWHERE IF) exists : ELSE ELSEWHERE : : ENDIF ENDIF 4. The conformability requirement. I may be out in left field with this one but as a dumb programmer it sure looks to me like there could be a natural mapping of A(1:N-1) into the logical expression L(1:N). Its been pointed out to me that in the more general case the mapping of A(ilower:iupper) into L(1:N) is not defined, and gets even worse if you add a stride as in L(1:N:ISTRIDE) but would it make sense to say that if the bounds were constants or used the same variable +- a constant that a mapping could be defined? I'd be interested in other peoples comments on the WHERE statment, it seems very limited and inflexible to me. --dave (opinions my own) David Levine levine@mcs.anl.gov Mathematics and Computer Science {alliant,sequent,rogue}!anlams!levine 9700 Cass Avenue South (312) 972-6735 Argonne National Laboratory Argonne, Illinois 60439 -------------------Original Fortran 77 code fragment------------------------ Below is the Fortan 77 code. It only contains one of 6 similar IF tests. [i1 is used to determine the neighbor cell in the row above (below). ] [It varies for even and odd rows because a hexagonal lattice is being ] [ mapped into a rectangular grid. ] DO 10 i = 1, n DO 20 j = 1, n IF ( state(i,j) .eq. 1 ) THEN : IF ( sortie(i,j) .gt. 0 ) THEN : IF ((p6 .gt. 0) .and. (p1 .lt. 0) .and. (d1 .gt. 0)) THEN tx(i,j) = x(i,j) - bp ty(i,j) = y(i,j) - ap outne(i,j) = 1 IF (( i1 .lt. n) .or. ( j .lt. n )) THEN insw(i1+1,j+1) = 1 ENDIF ENDIF : ENDIF : ENDIF 20 CONTINUE 10 CONTINUE -----------Manually Converted Fortran 8x code fragment------------------------ The code above was turned into the following Fortran 8x code. WHERE (state .EQ. 1) : ENDWHERE : WHERE ((state .EQ. 1) .AND. (sortie .gt. 0)) : ENDWHERE : WHERE ((state .EQ. 1) .AND. + (p6.GT.0) .AND. + (p1.LT.0) .AND. + (d1.GT.0)) tx = x - bp ty = y - ap outne = 1 ENDWHERE WHERE ((state(2:n:2,1:n) .EQ. 1) .AND. + (p6(2:n:2,1:n).GT.0) .AND. + (p1(2:n:2,1:n).LT.0) .AND. + (d1(2:n:2,1:n).GT.0)) insw(1:n-1:2,1:n) = 1 ENDWHERE WHERE ((state(3:n-1:2,1:n-1) .EQ. 1) .AND. + (sortie(3:n-1:2,1:n-1).GT.0) .AND. + (p6(3:n-1:2,1:n-1).GT.0) .AND. + (p1(3:n-1:2,1:n-1).LT.0) .AND. + (d1(3:n-1:2,1:n-1).GT.0)) insw(2:n-2:2,2:n) = 1 ENDWHERE
fisher@Alliant.COM (Larry Fisher) (10/27/89)
I have one question in regard to the "conversion" of a DO loop with nested IFs to a Fortran 8X WHERE block: Why do the conversion? Working with the Alliant Fortran compiler, I have the option of using WHERE blocks when porting and tuning code. However, I find that it is rarely worth the time to do the conversion for a number of reasons. First, I assume that the reason for using WHERE is to get (force) the DO/nested IF structure to be mapped to vector hardware instructions. As a practical matter on today's vector processors, vectorized IF statements are worthwhile only if the conditionally-executed (cond-ex) statements are "frequently" executed. I quote the word frequently because the definition varies by machine and by computational complexity of the cond-ex code. Keeping the explanation brief, the implementation of vector IFs causes the cond-ex code to be executed *regardless* of whether or not the result will be used. The only part of the cond-ex code that is conditional is the storage into destination (left-hand-side) variables based on a mask; a mask that is the result of the IF statement's condition expression. Second, I (IMHO) view WHERE blocks to be a notational shorthand that is to be used where appropriate. The DO/nested IF example recently shown in this group is not one I would consider appropriate for a WHERE block. As was pointed out by the original poster, forcing the readable F78 code into a much-less-comprehensible F8x WHERE block doesn't make sense, never mind the fact that no equivalent to ELSEIF exists. Finally, It doesn't appear to me that the existing algorithm implemented in F78 is one that, without changes, will run effectively on vector hardware. Certainly we could discuss automatic mapping of DO/IF constructs to WHERE blocks by a Fortran compiler, as is done, where appropriate, by Alliant's FX/Fortran compiler, but that's just one of a number of other considerations tied to the above comments. "Opinions..." -- Larry Fisher Domain: fisher@alliant.com Alliant Computer Systems UUCP: {mit-eddie|linus}!alliant!fisher Littleton, MA 01460 Phone: (508) 486-1449
mcdonald@uxe.cso.uiuc.edu (10/27/89)
>At least for the example below, the 8x code seems awkward to write, and the >amount of it required greater than the necessary 77 code. The code fragments >are from a cellular automata program that implements a 2-d hexagonal lattice >on an N by N array. I simply don't understand this. Sine F8x is a superset of F77, how can F8x code be "more awkward to write" or the amount "greater than the necessart 77 code" - they are both impossible. Perhaps you could find an unsuited F8x construct, and write worse code using that construct - but you could use the older, more suitable constructs, and have "less awkward" and smaller code. Dpug McDonald