coforall-loops: loop-based tasking¶
The coforall statement can be used to create an arbitrary number
of related, homogeneous tasks. Syntactically, it mirrors the for-loop
statement, but uses the
coforall keyword in place of
Operationally, a coforall loop creates a distinct task per loop iteration, each of which executes a copy of the loop body. Mnemonically, the coforall loop can be thought of as a concurrent forall—that is, a parallel loop in which each iteration is a concurrent task.
As with the cobegin statement, the original task
does not proceed until the child tasks corresponding to the coforall’s
iterations have completed. And, as with
cobegin, the original
task waits only for its immediate children, not their descendents.
The following code illustrates a simple use of the coforall loop:
config const numTasks = 8; coforall tid in 1..numTasks do writeln("Hello from task ", tid, " of ", numTasks); writeln("Signing off...");
This program will create a number of tasks equal to the configuration constant numTasks. Each task executes the loop body, printing a hello message indicating the value of its unique, private copy of the loop index variable tid (think “task ID”) and the total number of tasks. As in previous examples, since the tasks are not coordinating with one another, their “Hello” messages will print out in an arbitrary order. However, the “Signing off…” message will not print until all the “Hello” messages have, since it will be executed by the original task only once the per-iteration tasks are done. Thus, the following shows a possible output of the test:
Hello from task 4 of 8 Hello from task 1 of 8 Hello from task 2 of 8 Hello from task 5 of 8 Hello from task 3 of 8 Hello from task 6 of 8 Hello from task 7 of 8 Hello from task 8 of 8 Signing off...