Next, we give a more complete description of CC++ . The presentation is loosely structured according to the design methodology of Chapter 2. First, we describe how CC++ programs specify concurrent execution. Then, we explain how CC++ programs specify locality. Next, we explain how to specify various communication structures. Finally, we describe how CC++ programs specify mapping. Along the way, we also address the issues of modularity and determinism.
A CC++ program, like a C++ program, executes initially as a single thread of control (task). However, a CC++ program can use par, parfor, and spawn constructs to create additional threads. A parallel block is distinguished from an ordinary C++ block by the keyword par, as follows.
par { statement1; statement2; ... statementN; }
A parallel block can include any legal CC++ statement except for variable declarations and statements that result in nonlocal changes in the flow of control, such as return.
Statements in a parallel block execute concurrently. For example, the following parallel block creates three concurrent threads: two workers and one master.
par { worker(); worker(); master(); }
A parallel block terminates when all its constituent statements terminate; execution then proceeds to the next executable statement. Thus, in the preceding parallel block, the thread that executed the parallel block proceeds to the next statement only when both the master and the workers have terminated.
A parallel for-loop creates multiple threads, all executing the same statements contained in the body of the for-loop. It is identical in form to the for-loop except that the keyword parfor replaces for. For example, the following code creates ten threads of control, each executing the function myprocess.
parfor (int i=0; i<10; i++) { myprocess(i); }
Only the loop body of the parfor executes in parallel. Evaluation of the initialization, test, and update components of the statement follows normal sequential ordering. If the initialization section uses a locally declared variable (for example, int i), then each instance of the loop body has its own private copy of that variable.
CC++ parallel constructs can be nested arbitrarily. Hence, the following code creates ten worker threads and one master.
par { master(); parfor (int i=0; i<10; i++) worker(i); }
Finally, the spawn statement can be used to specify unstructured parallelism. This statement can be applied to a function to create a completely independent thread of control. The parent thread does not wait for the new thread to terminate execution, and cannot receive a return value from the called function. As we shall see in Section 5.10, one use for the spawn statement is to provide an efficient implementation of RPCs that do not require a return value.
© Copyright 1995 by Ian Foster