3.2 INDEPENDENT的进一步例子 |
!HPF$ INDEPENDENT
DO I=1,10
WRITE(IOUNIT(I),100) A(I)
ENDDO
100 FORMAT(F10.4)
如果对于每一个i({1,...,10},IOUNIT(I)都估算出一个不同的值,则在每次迭代上循环都要写向一个不同的I/O单元(或者一个不同的文件)。然后就可将此循环正确地描述为独立的。另一方面,如果对于所有的I,IOUNIT(I)=5,则此声明就是错误的并且本指令不符合HPF标准。
!HPF$ INDEPENDENT, NEW(J)
DO I = 2, 100, 2
!HPF$ INDEPENDENT, NEW(VL, VR, UL, UR)
DO J =2, 100, 2
VL = P(I,J)-P(I-1,J)
VR = P(I+1,J)-P(I,J)
UL = P(I,J)-P(I,J-1)
UR = P(I,J+1)-P(I,J)
P(I,J) = F(I,J)+P(I,J)+0.25*(VR-VL+UR-UL)
ENDDO
ENDDO
如果没有J循环上的NEW子句,则哪一个循环都不是独立的,这是因为循环迭代的交叉执行可能导致在对P(I,J)赋值时使用VL,VR,UL,和UR其它的值,而不是同一循环迭代所计算出的那些值。可是,NEW子句指明如果每个循环迭代使用不同的存储单元就是不对的。使用这一实现使得循环迭代之间相互独立。注意由于循环步长的原因,对数组P访问没有冲突(例如,I和J总是偶数,因此I-1等,总是奇数)
当循环是嵌套时,即使所发生的归约操作被嵌套在内层循环中,也需要在INDEPENDENT外层循环中将归约变量保护起来。而且,内层循环和任何交叉循环可以是独立的也可以是不独立的。
!嵌套循环例 1。内层循环是串行的。
X=10
OUTER: DO WHILE (X<1000) !此循环是串行的
!HPF$ INDEPENDENT, NEW(J), REDUCTION(X)
MIDDLE: DO I=1, N
INNER: DO J=1, M
X=X+J
!注意,除非在归约语句中,
!否则在这里引用X是不正确的。
ENDDO INNER
!注意,除非在归约语句中,
!否则在这里引用X是不正确的。
ENDDO MIDDLE
PRINT *, X
ENDDO OUTER
因为变量X出现在循环MIDDLE的一个归约子句中,因此它在整个该循环中是一个受保护的归约变量,包括在内部循环中。如果INNER有一个INDEPENDENT指令,则在该指令的REDUCTION或NEW子句中包含X是不正确的。最外层循环不是独立的,因此X无须也不能在它的范围中且中间循环外面受保护。
NEW子句中出现的变量不能是同一循环或某一外层循环中的归约变量,但可在内层循环中将其用作一个归约变量:
!嵌套循环例2。外层循环NEW子句。
!HPF$ INDEPENDENT, NEW(I)
OUTER: DO K=1,100
!HPF$ INDEPENDENT, NEW(J,X)
MIDDLE: DO I=1,N
X=10
!HPF$ INDEPENDENT, REDUCTION(X)
INNER: DO J=1,M
X=X+J**2
!注意,除非在归约语句中,
!否则在这里引用X是不正确的。
ENDDO INNER
Y(I)=X
ENDDO MIDDLE
ENDDO OUTER
在这里,X仅能在内层循环中是一个受保护的归约变量。
INTEGER, DIMENSION(M) :: VECTOR
!HPF$ INDEPENDENT, REDUCTION(X,Y)
DO I=1,N
X(I:I+4)=X(I:I+4)+<ERR> !更新5次
Y(VECTOR)=Y(VECTOR)+<VECTOR-EXPR)
ENDDO
如果此循环迭代是在块方式中分配的,则编译器无须为整个数组X建立一个私有拷贝。
当一个INDEPENDENT循环活动时,如果一个语句是以归约语句的形式出现的,但被更新的变量不是一个受保护的归约变量,则程序员必须保证任意两个INDEPENDENT的迭代不会对同一位置进行更新。例如:
!HPF$ INDEPENDENT
DO I=1,N
!我知道在INDX(1:N)中没有重复值
!且X不是归约变量。
!更新将被直接写入X(INDX(I))中
X(INDX(I))=X(INDX(I))+F(I)
!我也保证IF语句中的条件无论对于0
!还是对于i的某一值都为真
IF(A(I)>B(I)) Y=Y+1
END DO
Copyright: NPACT |