P2 Parallel Programming Package Th. Christopher January 1992 (revised Aug. 93) The P2 Parallel Programming Package is adapted from the P4 package developed at Argonne. A Master process initializes the package and then creates a collection of Slave processes. All slave processes execute the procedure "slave()". The processes then communicate by sending messages to each other. p2_initenv() p2_create_procgroup() p2_wait_for_end() p2_get_my_id() p2_num_total_slaves() p2_clock() p2_send() p2_sendr() p2_recv() p2_msg_free() p2_messages_available() The first executable statement in a p2 master program should be: p2_initenv(); This initializes the p2 system. The statement: p2_create_procgroup(n); creates the set of n slaves. Obviously this statement must be executed before any slaves can be assumed to exist. unsigned int p2_clock() returns an integer value indicating the current time. The resolution of the clock is hardware dependent. You can subtract one clock time from another to determine the length of time that some computation takes. The clock routine takes advantage of a high-resolution clock on the Encore. void p2_create_procgroup(n) int n; The p2-managed processes are automatically assigned successive numbers (beginning with 0 for the master); they have message queues allocated so that they can do message-passing, and they are able to run either on a shared-memory multiprocessor with the creating process or on a separate machine. (On the Encore, they run on the same computer, sharing the processors.) Each created process executes a parameterless procedure named "slave". To terminate, it returns from the slave procedure. P2 supports a set of send/receive procedures. These procedures are "generic" in the sense that the user does not know whether a message must travel across a network or through shared memory. (They depend on a lower-level set of procedures that handle local or network (remote) communications.) int p2_messages_available(req_type,req_from) int *req_type,*req_from; returns a int value indicating whether the process has any messages available or not (C conventions: nonzero, yes; zero, none). Req_type and req_from are both pointers to integers; they are used as both input and results. On input, req_type has a value that indicates the type of message that the user wishes to check for availability (-1 indicates any type). Req_from is used similarly to indicate whom a message is desired from. If the routine finds a message and returns non-zero, it assigns the message's type and source process number to req_type and req_from. void p2_send(type,to,msg,len) int type,to,len; char *msg; sends the message (a character string) of the specified type to the process with p2-id given in "to". The length of the message is given in "len". void p2_sendr(type,to,msg,len) int type,to,len; char *msg; stands for p2_send with "rendezvous". It is identical to p2_send with one exception, it waits for an acknowledgement that the message was received. Note that this acknowledgement is provided by p2 and is not sent by the user program. void p2_recv(req_type,req_from,msg,len_rcvd) int *req_type,*req_from,*len_rcvd; char **msg; takes five arguments. The msg argument is a "pointer to a pointer" to char that is assigned the address of a received message. The len_rcvd argument is a pointer to an integer that is assigned the length of the received message. Req_type and Req_from are both pointers to integers; they are used as both input and arguments. On input, req_type has a value that indicates the type of message that the user wishes to receive (-1 indicates any type). It will block until a message of that type is available. Req_from is used similarly to indicate whom a message is desired from. One important note about this procedure is that it obtains the area in which to place a message, and the user must explicitly free that area when finished with it (see p2_msg_free below). void p2_msg_free(m) char *m; frees the message pointed to by "m". This procedure should be used for this task because a message has hidden information which the user is unaware of and therefore cannot free himself. int p2_get_my_id() returns an integer value representing the id of the process assigned by the p2 system. void p2_initenv() should be called by your master process before an attempt is made to start any processes or to use any p2 procedures or data areas. We suggest making it the first executable statement in your master program. int p2_num_total_slaves() returns an integer value indicating the total number of slaves started by p2_create_procgroup. void p2_wait_for_end() is the p2 termination/cleanup procedure that you should invoke at the end of every execution of a program that uses p2. It should be invoked exactly once at the end of the run (in the master process). It does some termination processing and then waits for p2-managed slave processes to end.