We next give a more complete description of FM. The presentation is loosely structured according to the design methodology given in Chapter 2. First, we describe how FM programs define and create processes. Then, we explain how to specify various communication structures. Finally, we describe FM's mapping constructs. Along the way, we also address the issues of modularity and determinism.
The first step in the development of an FM program is typically to define the tasks from which a computation will be constructed. As noted in Example 6.1, a task is implemented in FM as a process. A process definition has the same syntax as a subroutine except that the keyword PROCESS is used in place of subroutine, and common data are labeled PROCESS COMMON to emphasize that they are common only to the process and any subroutines that it calls. Processes cannot share common data.
A process definition also defines the process's interface to its environment. A process's dummy arguments (formal parameters) are a set of typed port variables. (For convenience, conventional argument passing is also permitted between a process and its parent. This feature is discussed in Section 6.7.) A port variable declaration has the general form
port_type ( data_type_list ) name_list
The port_type is OUTPORT or INPORT and specifies whether the port is to be used to send or receive data, respectively. The data_type_list is a comma-separated list of type declarations and specifies the format of the messages that will be sent on the port, much as a subroutine's dummy argument declarations define the arguments that will be passed to the subroutine.
In Program 6.1, both pi and po are used to communicate messages comprising single integers. The following are examples of more complex message formats. In the second and third declaration, the names m and x have scope local to the port declaration. Notice how in the third declaration, the size of the array x is specified in the message.
INPORT (integer, real) p1 ! One integer, one real
INPORT (real x(128)) p2 ! Array of 128 reals
INPORT (integer m, real x(m)) p3 ! One integer ( m); m reals
The value of a port variable is initially a distinguished value NULL and can be defined to be a reference to a channel by means of the CHANNEL, RECEIVE, MERGER, or MOVEPORT statements, to be defined in the following sections.
Having defined one or more processes, we next construct a concurrent computation by creating instances of these processes. An FM program executes initially as a single process. This process can both execute sequential Fortran code and use process block and process do-loop constructs to create additional processes. A process block has the general form
PROCESSES statement_1 ... statement_n ENDPROCESSES
where and the statements are process calls, process do-loops, and/or at most one subroutine call. A process call has the same syntax as a subroutine call except that the keyword PROCESSCALL is used in place of the keyword call.
Statements in a process block execute concurrently. For example, the following parallel block creates three concurrent processes: two workers and a single process_master.
PROCESSES PROCESSCALL worker(pi1) PROCESSCALL worker(pi2) PROCESSCALL process_master(po1,po2) ENDPROCESSES
A process block terminates when all constituent statements terminate; execution then proceeds to the next executable statement. Thus, the parent process in this example proceeds to the statement after the parallel block only when both the the master and the workers have terminated execution.
A subroutine call in a parallel block allows the parent process to execute concurrently with the newly created processes. For example, the following variant of the preceding parallel block causes the current process to execute the subroutine subroutine_master concurrently with the two worker processes. Only two new processes are created, rather than three, and the subroutine can share common data with the calling process.
PROCESSES PROCESSCALL worker(pi1) PROCESSCALL worker(pi2) call subroutine_master(po1,po2) ENDPROCESSES
A process do-loop creates multiple instances of the same process. It is identical in form to the do-loop except that the keyword PROCESSDO is used in place of the keyword do and the body can include only a process do-loop or a process call. For example, the following code creates ten instances of myprocess.
PROCESSDO i = 1,10 PROCESSCALL myprocess ENDPROCESSDO
Process do-loops can be nested inside both process do-loops and process blocks. Hence, the following code creates ten worker processes and one master.
PROCESSES PROCESSCALL master PROCESSDO i = 1,10 PROCESSCALL worker ENDPROCESSDO ENDPROCESSES
© Copyright 1995 by Ian Foster