Task Parallelism

View taskParallel.chpl on GitHub

This primer illustrates Chapel's parallel tasking features, namely the begin, cobegin, and coforall statements.

config const n = 10; // Used for the coforall loop

Begin Statements

The begin statement spawns a thread of execution that is independent of the current (main) thread of execution.

writeln("1: ### The begin statement ###");

begin writeln("1: output from spawned task");

The main thread of execution continues on to the next statement. There is no guarantee as to which statement will execute first.

writeln("1: output from main task");

Cobegin Statements

For more structured behavior, the cobegin statement can be used to spawn a block of tasks, one for each statement. Control continues after the cobegin block, but only after all the tasks within the cobegin block have completed.

writeln("2: ### The cobegin statement ###");

cobegin {
  writeln("2: output from spawned task 1");
  writeln("2: output from spawned task 2");
}

The output from within the cobegin statement will always precede the following output from the main thread of execution.

writeln("2: output from main task");

If any begin statements are used within a cobegin statement, the thread of execution does not wait for those begin statements to complete.

writeln("3: ### The cobegin statement with nested begin statements ###");

cobegin {
  begin writeln("3: output from spawned task 1");
  begin writeln("3: output from spawned task 2");
}

The order of the output is again undefined because the begin statements in the above cobegin statement are not guaranteed to have been executed before control reaches the following statement.

writeln("3: output from main task");

Coforall Statements

Another more structured form of task parallelism is the coforall statement. The coforall statement is a loop variant of the cobegin statement where each iteration of the loop is a separate task. Similar to the cobegin statement, every iteration of the coforall loop is a separate task and the main thread of execution does not continue until every iteration is complete.

writeln("4: ### The coforall statement ###");

coforall i in 1..n {
  writeln("4: output from spawned task 1 (iteration ", i, ")");
  writeln("4: output from spawned task 2 (iteration ", i, ")");
}

While the order of output within an iteration is deterministic (1 executes before 2), the order of output relative to other iterations is not defined. As with the cobegin statement, the output from within the coforall statement will always precede the following output.

writeln("4: output from main task");

As with the cobegin statement, any begin statements spawned within a coforall loop are not guaranteed to be complete before the main thread of execution continues.

writeln("5: ### The coforall statement with nested begin statements ###");
coforall i in 1..n {
  begin writeln("5: output from spawned task 1 (iteration ", i, ")");
  begin writeln("5: output from spawned task 2 (iteration ", i, ")");
}

The order of output is undefined.

writeln("5: output from main task");