To: J3 09-283 From: Bill Long Subject: DO CONCURRENT restrictions Date: 2009 August 11 References: J3/09-007r2 Discussion The current restrictions on variables referenced or defined in the body of a DO CONCURRENT construct include the following [177:13-14]: "A variable that is referenced in an iteration shall either be previously defined during that iteration, or shall not be defined or become undefined during any other iteration of the current execution of the construct." This implicitly assumes that a variable falls either into one of two categories, which can be labeled "private" (first clause of the sentence), or "shared" (remainder of the sentence), borrowing terminology from OpenMP. Which category a variable falls into affects how it is treated by the compiler. Unfortunately, there are cases where the categorization is not possible at compile time. Consider Example 1: do concurrent (i=1:n) if (c1(i)) t = a(i) if (c2(i)) b(i) = t end do If the elements of c1 are all false, then the variable t is "shared". On the other hand, if c2(i) and c1(i) are true for exactly the same set of values of i, then t is "private". or Example 2: do concurrent(i=1:n) w(ix(i):iy(i)) = c(i) = sum(w(ix(i):iy(i))) end do If the range ix(i):iy(i) is the whole size of w for every i, then w(ix(i):iy(i)) is "private". On the other hand, if the ranges partition the array a into non-overlapping, but covering subsets, then w should be "shared". Note that it whether w is defined after the loop completes depends on the choice. At a minimum, I would expect these examples to prompt an interp request if there are no changes in the draft text. In cases where the user knows that a particular variable, tmp, is "private" in the construct, even though the compiler cannot, this can be enforced with do concurrent ... block real :: tmp ... end block end do where the block might enclose only the subset of the loop where tmp is actually used. There seem to be two options: 1) Use the local declaration of an unsaved variable to make it "private". Edits are provided for this case. 2) Leave the text as is, but have the situation where the compiler will generate serial code for the construct if it cannot determine the "shared" or "private" category for every variable in the construct. Related to this topic, it is assumed here that local declarations in a BLOCK construct that is contained inside a DO CONCURRENT construct will cause separate variables to be created for every iteration. Based on how we treat local variables in recursive function referenced, for example, this seems like to "obvious" interpretation. It is less clear that we actually say this in the standard. Edits to 09-007r2 [177:13] In 8.1.6.7, para 1, first bullet, first sentence, delete "shall either be previously defined during that iteration, or,". [177:14-16] In 8.1.6.7, para 1, first bullet, delete the second sentence "A variable that is defined...". [177:28-] In 8.1.6.7 Restrictions on DO CONCURRENT constructs, after Note 8.9, add a new Note: "Note 8.9a Variables local to each iteration of a DO CONCURRENT construct can be declared within a BLOCK construct within the block of the DO CONCURRENT construct. For example DO CONCURRENT (I = 1:N) BLOCK REAL :: T T = A(I) + B(I) C(I) = T + SQRT(T) END BLOCK END DO is allowed because T is a separate variable in each iteration."