%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%W  pargap2.tex            ParGAP documentation            Gene Cooperman
%%
%H  $Id: pargap2.tex,v 1.3 2001/07/28 23:49:06 gap Exp $
%%
%Y  Copyright (C) 1999-2001  Gene Cooperman
%Y    See included file, COPYING, for conditions for copying
%%

\Chapter{Slave Listener}

{\ParGAP} implements a model of a slave process as  a  *slave  listener*.
This means that the slave is running a simple program:

\begintt
  (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
\endtt

An example using this interactive style is contained in section~"Extended
Example".

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  `FlushAllMsgs()'  (see~"FlushAllMsgs").  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 `Error' 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 `ParReset();' (see~"ParReset")
to interrupt all slave processes and return them to their top level  loop
as a slave listener.

At this point, you may wish to review the commands by  looking  again  at
the extended example in section~"Extended Example". Note also some naming
conventions:

\beginitems
`MPI_...':&
A command prefix of `MPI_' signifies a {\GAP} binding of an MPI function.
These functions are low level functions on which the rest of {\ParGAP} is
built. They can be safely ignored by the casual user. (Recall  that  MPI,
*Message Passing Interface*, is  a  standard  for  message  passing.)  In
{\ParGAP}, type `MPI_\<<tab>>' for a list of all such functions.

`UNIX_...':&
Commands with prefix `UNIX_' are additional system commands that were not
present in the  unmodified  {\GAP}  kernel.  They  are  typically  {\GAP}
versions of UNIX commands that make  life  easier.  `UNIX_Nice()'  is  an
example. In {\ParGAP}, type  `UNIX_\<<tab>>'  for  a  list  of  all  such
functions.

`Par...':&
Commands beginning with `Par' are ``parallel'' commands that should  only
be called by the master process. Such commands invoke all slave processes
to do their work. In {\ParGAP}, type `Par\<<tab>>' for a list of all such
functions.

\enditems

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\Section{Slave Listener Commands}

The  slave  listener  commands  are  implementd   in   `slavelist.g'   in
{\ParGAP}'s `lib' directory. Most procedures are short, and can  also  be
read online by using {\GAP}'s `Print' command, e.g.~try:  `Print(SendMsg,
"\\n");' (the newline is needed only to get back to a  clean  ```gap> '''
prompt). The  code  of  `SlaveListener'  and  `CloseSlaveListener'  (try:
`Print(SlaveListener, "\\n");' and  `Print(CloseSlaveListener,  "\\n");')
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~"Extended Example". Some  of  these  commands  are
based on MPI. Further information on basic concepts of MPI can  be  found
in section~"Tutorial introduction to the MPI C library", but that section
can be safely ignored on a first reading.

\>SendMsg( <command>[, <dest>[, <tag>]] ) F

sends <command> to <dest> (a non-negative integer that is the ``rank'' of
the  destination  process);  <command>  should  normally  be   a   string
(otherwise it is evaluated on the master before being  passed  to  <dest>
which almost certainly will defeat the purpose of using `SendMsg()').  If
<dest> is omitted it defaults to 1 (the rank of the first slave)  on  the
master process (i.e.~if `IsMaster()' is `true'), or to 0 (the rank of the
master) on  a  slave  process  (i.e.~if  `IsMaster()'  is  `false').  The
argument <tag>, if given, should be a positive integer  less  than  1000.
The default value of <tag> is  1.  Tags  of  value  1000  and  above  are
reserved for  use  by  {\ParGAP}  itself,  and  should  not  be  used  by
application routines.

\>RecvMsg( [<source>] ) F

gets a response  from  a  command.  The  default  value  of  <source>  is
`MPI_ANY_SOURCE', which receives the  next  available  message  from  any
source.  `GetLastMsgSource()'  (see~"GetLastMsgSource")  allows  one   to
determine    the    source    in    such     cases.     `GetLastMsgTag()'
(see~"GetLastMsgTag") always allows one to determine  the  tag,  although
most applications can ignore the tag. Tags are  applied  to  commands  by
`SendMsg()' or `SendRecvMsg()' (see~"SendMsg").

\>GetLastMsgSource() F

returns the source of the last message that was either received  (e.g.~by
`RecvMsg()';  see~"RecvMsg")  or  simply  probed  (e.g.~by  `ProbeMsg()';
see~"ProbeMsg").

\>GetLastMsgTag() F

returns the tag (see~"SendMsg") of  the  last  message  that  was  either
received (e.g.~by `RecvMsg()'; see~"RecvMsg") or simply  probed  (e.g.~by
`ProbeMsg()'; see~"ProbeMsg").

\>SendRecvMsg( <command>[, <dest>[, <tag>]] ) F

This command is equivalent to `SendMsg( <command>[, <dest>[,  <tag>]]  );
RecvMsg([<dest>]);' (see~"SendMsg" and~"RecvMsg"), except  that  even  if
<dest> is omitted the source for the  `RecvMsg()'  part  of  the  command
always matches the destination to which <command> is sent.

*Note:*
The response obtained will not be the response of the <command> itself if
there are messages waiting to be received at the destination of <command>
at the time `SendRecvMsg()' is called.

Also note that tag values of 1000 and higher  are  reserved  for  use  by
{\ParGAP}.

\>BroadcastMsg( <command> ) F

executes <command> on (all) slaves only. The slaves do not  send  back  a
return value.

*Note:*
this use of the term *broadcast* is distinct from the MPI usage. In  MPI,
a broadcast message will be received  by  every  process,  including  the
process sending the message.

\>IsMaster() F

returns `true' if at console (i.e.~if `MPI_Comm_rank() = 0'), and `false'
otherwise.

\>FlushAllMsgs() F

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 `RecvMsg();;'  until
there are no more messages waiting to be received (see~"RecvMsg"), except
that it also returns the number of messages flushed.

\>PingSlave( <dest> ) F

Check if slave <dest> is alive and listening for messages,  where  <dest>
is a positive integer.

\>ParEval( <stringCmd> ) F

Evaluate <stringCmd> on all processes, where  <stringCmd>  is  a  command
inside  double  quotes  so  that  it  is  passed  as   a   string   (like
`BroadcastMsg()' (see~"BroadcastMsg"),  but  `ParEval()'  (see~"ParEval")
also executes on the master and also returns a value based on  result  on
the master.)

\>PrintToString( <object> [, ...] )

   [Note that `PrintToString("abc") => "abc"' 
    (like `Print()', NOT `"\"abc\""')
     Hence, a useful idiom is:  `ParEval( PrintToString( "foo := ", foo ) );'  ]

\>ParRead( <filename> ) F
\>ParReread( <filename> ) F

are parallel analogues of  the  {\GAP}  `Read'  and  `Reread'  functions,
respectively (see~"ref:Read" and~"ref:Reread" in the  Reference  Manual).
`ParRead' (resp. `ParReread') executes `Read'  (resp.  `Reread')  on  all
processes. Note that it  is  redundant  (and  often  incorrect)  to  call
`ParRead' on a file that itself contains `Par...' functions.  One  should
either place sequential functions in a file and call `ParRead'  or  place
`Par...' functions in a file and call  `Read'  from  the  master.  As  an
example, in writing this code, the author (after having started {\ParGAP}
from its `bin'  directory  via  `pargap.sh')  found  it  useful  to  edit
`masslave.g'   in   {\ParGAP}'s   `lib'   directory   and    then    type
`ParReread("../lib/masslave.g");'.

\>ParList( <list>, <func> ) F

is the parallel analogue of {\GAP}'s two-argument  `List'  function.  But
faster since it also uses the slave processes.

\>ProbeMsg( [<source>] ) F

probes for a pending message from <source> or any source if the  argument
<source> is omitted. It will block until such a message appears, and then
return `true'. `^C' (interrupt) works to unblock it.

*Note:*
When the argument  <source>  is  omitted,  `ProbeMsg'  sets  <source>  to
`MPI_ANY_SOURCE' (which is `-1'), which specifies a probe for  a  message
from any source.

\>ProbeMsgNonBlocking( [<source>] ) F

Exactly like `ProbeMsg', but non-blocking. It  returns  immediately  with
`true' or `false', depending  on  whether  a  message  was  present  from
<source>. The default value of <source> is `MPI_ANY_SOURCE'.

\>ParReset() F

flushes all pending messages from slaves, resets the  slaves,  pings  the
slaves and returns the number of messages flushed.

\>ParBindGlobal( <gvar>, <value> ) F

Not currently implemented, due to certain technical considerations.

\>ParDeclareGlobalValue( <string> ) F
\>ParDeclareGlobalFunction( <string> ) F

Similar to corresponding {\GAP}  functions.  Note  that  unlike  {\GAP}'s
`DeclareGlobalFunction' and `ParDeclareGlobalValue', 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 `InstallGlobalFunction'
and `InstallValue'. This  eliminates  the  necessity  for  `Reread()'  in
{\ParGAP}, and it also makes it easier to place the commands in  a  local
file, and using a simple `Read()' instead of `ParRead()'. It  also  makes
it easier to interactively re-declare and re-install functions.

\>ParInstallValue( <gvar>, <value> ) F
\>ParInstallValue( <string>, <value> ) F
\>ParInstallGlobalFunction( <gvar>, <function> ) F
\>ParInstallGlobalFunction( <string>, <function> ) F

Note  that  the  second  version  of   `ParInstallGlobalFunction'   (with
<string>) is equivalent to

\){\kernttindent}ParDeclareGlobalFunction( <string> );
\){\kernttindent}ParInstallGlobalFunction( <gvar>, <function> );

where <gvar> is a {\GAP} variable whose name is <string>.

Note that `ParInstallValue' is currently implemented only in the  version
for <string>, due to certain technical considerations.

This completes the middle layer of {\ParGAP}. 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~"MPI  commands  and  UNIX  system  calls  in
ParGAP".

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%E
