Subject: Re: Forall

From: [email-masked] (Min-You Wu)
Date: Sat, 27 Jun 92 14:06:42 EDT

> > > 	FORALL ( I = 1:N ) A(I) = MESSY_FUNCTION( I, B(I), INDX(:) )
> 
> 	REAL FUNCTION MESSY_FUNCTION( K, A, IA )
> 	INTEGER K
> 	INTEGER, DIMENSION(:) :: IA
> 	REAL A(K)
>S1: 	A(1) = 1.0		! assign to B(I)
>S2: 	A(IA(K)-K+1) = 2.0	! assign to B(INDX(K)) [ note
> 				! subscript offset tricks ] 
> 	DO I = LBOUND(IA), UBOUND(IA)
>S3: 	  PRINT IA(I)		! reference all of INDX
>S4: 	  IA(I) = 3.0		! assign all of INDX
> 	ENDDO
>S5: 	MESSY_FUNCTION = A(IA(K))
> 	END
> 
> Chuck
> 

I will use this example to illustrate some thought about function calls
in FORALL.

First, this MESSY_FUNCTION cannot be called from an INDEPENDENT block
because there is an output dependence (S1 and S2), an anti-dependence
(S2 and S4), and data (true) dependences (S4 and S5, S1,S2 and S5).  
Furthermore, S4 is not valid to be included in a FORALL since INDX(I) 
will be assigned N times (though the same value).  Although S3 is a 
valid statement, INDX will be printed N times.  S2 is valid assuming 
INDX is a permutation.  

Let me make a few functions that are valid to be called from an INDEPENDENT
block:

=========================================================================
 	REAL FUNCTION NOT_MESSY_FUNCTION1( K, A, IA )
 	INTEGER K
 	INTEGER, DIMENSION(:) :: IA
 	REAL A(K)
S1: 	A(1) = 1.0		! assign to B(I)
S6: 	NOT_MESSY_FUNCTION1 = A(1)
 	END

=========================================================================
 
 	REAL FUNCTION NOT_MESSY_FUNCTION2( K, A, IA )
 	INTEGER K
 	INTEGER, DIMENSION(:) :: IA
 	REAL A(K)
S2: 	A(IA(K)-K+1) = 2.0	! assign to B(INDX(K)) [ note
 				! subscript offset tricks ] 
S7: 	NOT_MESSY_FUNCTION2 = A(IA(K)-K+1)
 	END
 
=========================================================================

 	REAL FUNCTION NOT_MESSY_FUNCTION3( K, A, IA )
 	INTEGER K
 	INTEGER, DIMENSION(:) :: IA
 	REAL A(K)
 	DO I = LBOUND(IA), UBOUND(IA)
S3: 	  PRINT IA(I)		! reference all of INDX
 	ENDDO
S5: 	NOT_MESSY_FUNCTION3 = A(IA(K))
 	END
 
=========================================================================

The function calls (as well as subroutine calls) to be included in an
INDEPENDENT block must have some restrictions.  Simply speaking, the 
restriction is "NO DEPENDENCE".  In my INDEPENDENT proposal, no function 
calls can be made from a non-independent block.  However, I am not sure 
if it is possible to do so.  Let's exam Chuck's example:

 	REAL FUNCTION MESSY_FUNCTION( K, A, IA )
 	INTEGER K
 	INTEGER, DIMENSION(:) :: IA
 	REAL A(K)
S1: 	A(1) = 1.0		! assign to B(I)
S2: 	A(IA(K)-K+1) = 2.0	! assign to B(INDX(K)) [ note
 				! subscript offset tricks ] 
 	DO I = LBOUND(IA), UBOUND(IA)
S3: 	  PRINT IA(I)		! reference all of INDX
S4: 	  IA(I) = 3.0		! assign all of INDX
 	ENDDO
S5: 	MESSY_FUNCTION = A(IA(K))
 	END
 
It cannot be called from an INDEPENDENT block.  When it is considered 
to be called from a non-independent block, there are two possible 
semantics (as I can see).  The first one is to force each instance 
of the call independent, that is, no interaction is permitted between 
instances of parallel calls (for simplicity, I will use "call" instead 
of "instance of parallel calls" in the following context).  Then we 
need to make copies for each call.  Each call will executeindependently, 
and at the end of call, some rule must be enforced to resolve possible
contention.  It is not the original Fortran semantics, but is close 
to Fortran D semantics. (Note that with this semantics S4 is valid).

The second semantics is to allow interaction between calls.  Then
we have to make some synchronizations in the function.  The function 
can be executed synchronously.  On the other hand, to reduce the number 
of synchronizations, we may apply INDEPENDENT directives inside of 
the function. 

 	REAL FUNCTION MESSY_FUNCTION( K, A, IA )
 	INTEGER K
 	INTEGER, DIMENSION(:) :: IA
 	REAL A(K)
!HPF$BEGIN INDEPENDENT
S1: 	A(1) = 1.0		! assign to B(I)
!HPF$END INDEPENDENT
!HPF$BEGIN INDEPENDENT
S2: 	A(IA(K)-K+1) = 2.0	! assign to B(INDX(K)) [ note
 				! subscript offset tricks ] 
!HPF$END INDEPENDENT
!HPF$BEGIN INDEPENDENT
 	DO I = LBOUND(IA), UBOUND(IA)
S3: 	  PRINT IA(I)		! reference all of INDX
 	ENDDO
S5: 	MESSY_FUNCTION = A(IA(K))
!HPF$END INDEPENDENT
 	END
 
Note that S4 is not valid and eliminated from the function.  I am not 
proposing INDEPENDENT directives in a function definition here.
I only want to see if INDEPENDENT blocks can be applied.  

I don't have a strong position at this moment on which semantics 
is better for HPF, or simply not allow calls from non-independent block.
However, as I see, a function call from non-independent block is possible.

Min-You