Parallelism in CM Fortran had to be expressed explicitly. The archetypal method of expressing this parallelism was by using the array assignments and intrinsic functions of Fortran 90. Conceptually this approach was equivalent to the vector assignments of CFD or the matrix assignments of DAP FORTRAN. Nearest neighbour communication, say, could be expressed along the lines
U = 0.25 * (CSHIFT(U, 1, -1) + CSHIFT(U, 1, +1) + CSHIFT(U, 2, -1) + CSHIFT(U, 2, +1))
Used for complex algorithms, the Fortran 90 array syntax often becomes verbose and difficult to read. In fact there are simple parallel operations that are difficult to express efficiently in array syntax at all. CM Fortran provided the powerful FORALL construct for these situations.
A FORALL statement allows a collection of assignments to designated array elements to be executed in parallel. It is a restricted form of parallel loop. The range of each loop index is defined by a triplet. To assign each element of the array IDENTITY with its own index value we could execute
FORALL(I = 1:N) IDENTITY(I) = IA nearest neighbour update might look something like
FORALL (I = 2:N-1, J = 2:N-1) & U(I,J) = 0.25 * (U(I,J-1) + U(I,J+1) + U(I-1,J) + U(I+1,J))
FORALL assignments had certain restrictions. In particular, no left-hand-side element could be assigned more than one value. A necessary but not sufficient condition is that subscript expressions in the left-hand-side must depend in some way on all loop indices. As in ordinary Fortran 90 array assignments, the semantics was supposed to be as if all expressions on the right-hand-side (for all values of loop indices) were completely evaluated before any assignments to the left-hand-side variables occurred9.
In spite of these restrictions, a general FORALL statement was a rather complicated thing to translate efficiently, especially considering that the assignment in the body of the FORALL could itself be an array assignment, or the expression on the right-hand-side could involve array intrinsics, as in the "parallel prefix":
FORALL (I = 1:N) SCAN(I) = SUM(A(1:I))or the matrix multiplication:
FORALL (I = 1:N, J = 1:N) C(I, J) = DOT_PRODUCT(A(I, :), B(:, J))In complex cases the CM Fortran had to resort to translating the FORALL statement as a serial loop.