<html><head><title>[ParGAP] 2 Slave Listener</title></head> <body text="#000000" bgcolor="#ffffff"> [<a href = "chapters.htm">Up</a>] [<a href ="CHAP001.htm">Previous</a>] [<a href ="CHAP003.htm">Next</a>] [<a href = "theindex.htm">Index</a>] <h1>2 Slave Listener</h1><p> <P> <H3>Sections</H3> <oL> <li> <A HREF="CHAP002.htm#SECT001">Slave Listener Commands</a> </ol><p> <p> <font face="Gill Sans,Helvetica,Arial">ParGAP</font> implements a model of a slave process as a <strong>slave listener</strong>. This means that the slave is running a simple program: <p> <pre> (1) Read message from master [as string] (2) Evaluate message and return result (3) Send message to master with result [as string] (4) Goto step 1 </pre> <p> An example using this interactive style is contained in section <a href="CHAP001.htm#SECT004">Extended Example</a>. <p> Some enhancements to this simple model should also be noted. The reply message from the slave will wait in a queue until the master process decides to read it. If unwanted messages accumulate in the queue, the master can execute <code>FlushAllMsgs()</code> (see <a href="CHAP002.htm#SSEC001.8">FlushAllMsgs</a>). If a slave process prints to the standard output, this will be visible at the console of the master process. If a slave process executes an <code>Error</code> and goes into a break loop, then it will automatically return to the top level, return any error message to the master process, and wait for another message from the master process. If a slave process goes into an infinite loop, the master process can call <code>ParReset();</code> (see <a href="CHAP002.htm#SSEC001.16">ParReset</a>) to interrupt all slave processes and return them to their top level loop as a slave listener. <p> At this point, you may wish to review the commands by looking again at the extended example in section <a href="CHAP001.htm#SECT004">Extended Example</a>. Note also some naming conventions: <p> <p> <dl compact> <dt><code>MPI_...</code>:<dd> A command prefix of <code>MPI_</code> signifies a <font face="Gill Sans,Helvetica,Arial">GAP</font> binding of an MPI function. These functions are low level functions on which the rest of <font face="Gill Sans,Helvetica,Arial">ParGAP</font> is built. They can be safely ignored by the casual user. (Recall that MPI, <strong>Message Passing Interface</strong>, is a standard for message passing.) In <font face="Gill Sans,Helvetica,Arial">ParGAP</font>, type <code>MPI_<</code><var>tab</var><code>></code> for a list of all such functions. <p> <dt><code>UNIX_...</code>:<dd> Commands with prefix <code>UNIX_</code> are additional system commands that were not present in the unmodified <font face="Gill Sans,Helvetica,Arial">GAP</font> kernel. They are typically <font face="Gill Sans,Helvetica,Arial">GAP</font> versions of UNIX commands that make life easier. <code>UNIX_Nice()</code> is an example. In <font face="Gill Sans,Helvetica,Arial">ParGAP</font>, type <code>UNIX_<</code><var>tab</var><code>></code> for a list of all such functions. <p> <dt><code>Par...</code>:<dd> Commands beginning with <code>Par</code> are ``parallel'' commands that should only be called by the master process. Such commands invoke all slave processes to do their work. In <font face="Gill Sans,Helvetica,Arial">ParGAP</font>, type <code>Par<</code><var>tab</var><code>></code> for a list of all such functions. <p> </dl> <p> <p> <a name="SECT001"><h2>2.1 Slave Listener Commands</h2></a> <p><p> The slave listener commands are implementd in <code>slavelist.g</code> in <font face="Gill Sans,Helvetica,Arial">ParGAP</font>'s <code>lib</code> directory. Most procedures are short, and can also be read online by using <font face="Gill Sans,Helvetica,Arial">GAP</font>'s <code>Print</code> command, e.g. try: <code>Print(SendMsg, "\n");</code> (the newline is needed only to get back to a clean ``<code>gap> </code>'' prompt). The code of <code>SlaveListener</code> and <code>CloseSlaveListener</code> (try: <code>Print(SlaveListener, "\n");</code> and <code>Print(CloseSlaveListener, "\n");</code>) is also instructive and should provide some insights into the behavior of the slave listener. Examples of slave listener commands can be found in context in the section <a href="CHAP001.htm#SECT004">Extended Example</a>. Some of these commands are based on MPI. Further information on basic concepts of MPI can be found in section <a href="CHAP007.htm#SECT001">Tutorial introduction to the MPI C library</a>, but that section can be safely ignored on a first reading. <p> <a name = "SSEC001.1"></a> <li><code>SendMsg( </code><var>command</var><code>[, </code><var>dest</var><code>[, </code><var>tag</var><code>]] ) F</code> <p> sends <var>command</var> to <var>dest</var> (a non-negative integer that is the ``rank'' of the destination process); <var>command</var> should normally be a string (otherwise it is evaluated on the master before being passed to <var>dest</var> which almost certainly will defeat the purpose of using <code>SendMsg()</code>). If <var>dest</var> is omitted it defaults to 1 (the rank of the first slave) on the master process (i.e. if <code>IsMaster()</code> is <code>true</code>), or to 0 (the rank of the master) on a slave process (i.e. if <code>IsMaster()</code> is <code>false</code>). The argument <var>tag</var>, if given, should be a positive integer less than 1000. The default value of <var>tag</var> is 1. Tags of value 1000 and above are reserved for use by <font face="Gill Sans,Helvetica,Arial">ParGAP</font> itself, and should not be used by application routines. <p> <a name = "SSEC001.2"></a> <li><code>RecvMsg( [</code><var>source</var><code>] ) F</code> <p> gets a response from a command. The default value of <var>source</var> is <code>MPI_ANY_SOURCE</code>, which receives the next available message from any source. <code>GetLastMsgSource()</code> (see <a href="CHAP002.htm#SSEC001.3">GetLastMsgSource</a>) allows one to determine the source in such cases. <code>GetLastMsgTag()</code> (see <a href="CHAP002.htm#SSEC001.4">GetLastMsgTag</a>) always allows one to determine the tag, although most applications can ignore the tag. Tags are applied to commands by <code>SendMsg()</code> or <code>SendRecvMsg()</code> (see <a href="CHAP002.htm#SSEC001.1">SendMsg</a>). <p> <a name = "SSEC001.3"></a> <li><code>GetLastMsgSource() F</code> <p> returns the source of the last message that was either received (e.g. by <code>RecvMsg()</code>; see <a href="CHAP002.htm#SSEC001.2">RecvMsg</a>) or simply probed (e.g. by <code>ProbeMsg()</code>; see <a href="CHAP002.htm#SSEC001.14">ProbeMsg</a>). <p> <a name = "SSEC001.4"></a> <li><code>GetLastMsgTag() F</code> <p> returns the tag (see <a href="CHAP002.htm#SSEC001.1">SendMsg</a>) of the last message that was either received (e.g. by <code>RecvMsg()</code>; see <a href="CHAP002.htm#SSEC001.2">RecvMsg</a>) or simply probed (e.g. by <code>ProbeMsg()</code>; see <a href="CHAP002.htm#SSEC001.14">ProbeMsg</a>). <p> <a name = "SSEC001.5"></a> <li><code>SendRecvMsg( </code><var>command</var><code>[, </code><var>dest</var><code>[, </code><var>tag</var><code>]] ) F</code> <p> This command is equivalent to <code>SendMsg( </code><var>command</var><code>[, </code><var>dest</var><code>[, </code><var>tag</var><code>]] ); RecvMsg([</code><var>dest</var><code>]);</code> (see <a href="CHAP002.htm#SSEC001.1">SendMsg</a> and <a href="CHAP002.htm#SSEC001.2">RecvMsg</a>), except that even if <var>dest</var> is omitted the source for the <code>RecvMsg()</code> part of the command always matches the destination to which <var>command</var> is sent. <p> <strong>Note:</strong> The response obtained will not be the response of the <var>command</var> itself if there are messages waiting to be received at the destination of <var>command</var> at the time <code>SendRecvMsg()</code> is called. <p> Also note that tag values of 1000 and higher are reserved for use by <font face="Gill Sans,Helvetica,Arial">ParGAP</font>. <p> <a name = "SSEC001.6"></a> <li><code>BroadcastMsg( </code><var>command</var><code> ) F</code> <p> executes <var>command</var> on (all) slaves only. The slaves do not send back a return value. <p> <strong>Note:</strong> this use of the term <strong>broadcast</strong> is distinct from the MPI usage. In MPI, a broadcast message will be received by every process, including the process sending the message. <p> <a name = "SSEC001.7"></a> <li><code>IsMaster() F</code> <p> returns <code>true</code> if at console (i.e. if <code>MPI_Comm_rank() = 0</code>), and <code>false</code> otherwise. <p> <a name = "SSEC001.8"></a> <li><code>FlushAllMsgs() F</code> <p> flushes all messages that are waiting to be received and returns the number of messages flushed. (If there are no waiting messages 0 is returned.) It is essentially equivalent to executing <code>RecvMsg();;</code> until there are no more messages waiting to be received (see <a href="CHAP002.htm#SSEC001.2">RecvMsg</a>), except that it also returns the number of messages flushed. <p> <a name = "SSEC001.9"></a> <li><code>PingSlave( </code><var>dest</var><code> ) F</code> <p> Check if slave <var>dest</var> is alive and listening for messages, where <var>dest</var> is a positive integer. <p> <a name = "SSEC001.10"></a> <li><code>ParEval( </code><var>stringCmd</var><code> ) F</code> <p> Evaluate <var>stringCmd</var> on all processes, where <var>stringCmd</var> is a command inside double quotes so that it is passed as a string (like <code>BroadcastMsg()</code> (see <a href="CHAP002.htm#SSEC001.6">BroadcastMsg</a>), but <code>ParEval()</code> (see <a href="CHAP002.htm#SSEC001.10">ParEval</a>) also executes on the master and also returns a value based on result on the master.) <p> <a name = "SSEC001.11"></a> <li><code>PrintToString( </code><var>object</var><code> [, ...] )</code> <p> [Note that <code>PrintToString("abc") => "abc"</code> (like <code>Print()</code>, NOT <code>""abc""</code>) Hence, a useful idiom is: <code>ParEval( PrintToString( "foo := ", foo ) );</code> ] <p> <a name = "SSEC001.12"></a> <li><code>ParRead( </code><var>filename</var><code> ) F</code> <a name = "SSEC001.12"></a> <li><code>ParReread( </code><var>filename</var><code> ) F</code> <p> are parallel analogues of the <font face="Gill Sans,Helvetica,Arial">GAP</font> <code>Read</code> and <code>Reread</code> functions, respectively (see <a href="../../../doc/htm/ref/CHAP009.htm#SSEC007.1">Read</a> and <a href="../../../doc/htm/ref/CHAP009.htm#SSEC007.13">Reread</a> in the Reference Manual). <code>ParRead</code> (resp. <code>ParReread</code>) executes <code>Read</code> (resp. <code>Reread</code>) on all processes. Note that it is redundant (and often incorrect) to call <code>ParRead</code> on a file that itself contains <code>Par...</code> functions. One should either place sequential functions in a file and call <code>ParRead</code> or place <code>Par...</code> functions in a file and call <code>Read</code> from the master. As an example, in writing this code, the author (after having started <font face="Gill Sans,Helvetica,Arial">ParGAP</font> from its <code>bin</code> directory via <code>pargap.sh</code>) found it useful to edit <code>masslave.g</code> in <font face="Gill Sans,Helvetica,Arial">ParGAP</font>'s <code>lib</code> directory and then type <code>ParReread("../lib/masslave.g");</code>. <p> <a name = "SSEC001.13"></a> <li><code>ParList( </code><var>list</var><code>, </code><var>func</var><code> ) F</code> <p> is the parallel analogue of <font face="Gill Sans,Helvetica,Arial">GAP</font>'s two-argument <code>List</code> function. But faster since it also uses the slave processes. <p> <a name = "SSEC001.14"></a> <li><code>ProbeMsg( [</code><var>source</var><code>] ) F</code> <p> probes for a pending message from <var>source</var> or any source if the argument <var>source</var> is omitted. It will block until such a message appears, and then return <code>true</code>. <code>^C</code> (interrupt) works to unblock it. <p> <strong>Note:</strong> When the argument <var>source</var> is omitted, <code>ProbeMsg</code> sets <var>source</var> to <code>MPI_ANY_SOURCE</code> (which is <code>-1</code>), which specifies a probe for a message from any source. <p> <a name = "SSEC001.15"></a> <li><code>ProbeMsgNonBlocking( [</code><var>source</var><code>] ) F</code> <p> Exactly like <code>ProbeMsg</code>, but non-blocking. It returns immediately with <code>true</code> or <code>false</code>, depending on whether a message was present from <var>source</var>. The default value of <var>source</var> is <code>MPI_ANY_SOURCE</code>. <p> <a name = "SSEC001.16"></a> <li><code>ParReset() F</code> <p> flushes all pending messages from slaves, resets the slaves, pings the slaves and returns the number of messages flushed. <p> <a name = "SSEC001.17"></a> <li><code>ParBindGlobal( </code><var>gvar</var><code>, </code><var>value</var><code> ) F</code> <p> Not currently implemented, due to certain technical considerations. <p> <a name = "SSEC001.18"></a> <li><code>ParDeclareGlobalValue( </code><var>string</var><code> ) F</code> <a name = "SSEC001.18"></a> <li><code>ParDeclareGlobalFunction( </code><var>string</var><code> ) F</code> <p> Similar to corresponding <font face="Gill Sans,Helvetica,Arial">GAP</font> functions. Note that unlike <font face="Gill Sans,Helvetica,Arial">GAP</font>'s <code>DeclareGlobalFunction</code> and <code>ParDeclareGlobalValue</code>, these functions also allow you to re-declare an old function or variable. The net effect is to remove the old value, and allow one to again call <code>InstallGlobalFunction</code> and <code>InstallValue</code>. This eliminates the necessity for <code>Reread()</code> in <font face="Gill Sans,Helvetica,Arial">ParGAP</font>, and it also makes it easier to place the commands in a local file, and using a simple <code>Read()</code> instead of <code>ParRead()</code>. It also makes it easier to interactively re-declare and re-install functions. <p> <a name = "SSEC001.19"></a> <li><code>ParInstallValue( </code><var>gvar</var><code>, </code><var>value</var><code> ) F</code> <li><code>ParInstallValue( </code><var>string</var><code>, </code><var>value</var><code> ) F</code> <a name = "SSEC001.19"></a> <li><code>ParInstallGlobalFunction( </code><var>gvar</var><code>, </code><var>function</var><code> ) F</code> <li><code>ParInstallGlobalFunction( </code><var>string</var><code>, </code><var>function</var><code> ) F</code> <p> Note that the second version of <code>ParInstallGlobalFunction</code> (with <var>string</var>) is equivalent to <p> <code>ParDeclareGlobalFunction( </code><var>string</var><code> );</code> <br><code>ParInstallGlobalFunction( </code><var>gvar</var><code>, </code><var>function</var><code> );</code> <p> where <var>gvar</var> is a <font face="Gill Sans,Helvetica,Arial">GAP</font> variable whose name is <var>string</var>. <p> Note that <code>ParInstallValue</code> is currently implemented only in the version for <var>string</var>, due to certain technical considerations. <p> This completes the middle layer of <font face="Gill Sans,Helvetica,Arial">ParGAP</font>. It allows one to easily use parallelism interactively. There are now two choices for further reading. The recommended choice for writing your own parallel applications is to read the next chapter on the TOP-C task-oriented model of parallelism, and the follow-on chapter, containing a tutorial on the TOP-C model. These two chapters should provide enough background to write significant parallel applications. If on the other hand you are interested in MPI and the low-level fundamentals of message passing for parallel applications, then you should read Chapter <a href="CHAP007.htm">MPI commands and UNIX system calls in ParGAP</a>. <p> <p> [<a href = "chapters.htm">Up</a>] [<a href ="CHAP001.htm">Previous</a>] [<a href ="CHAP003.htm">Next</a>] [<a href = "theindex.htm">Index</a>] <P> <address>ParGAP manual<br>November 2001 </address></body></html>