ParGAP implements a model of a slave process as a slave listener. This means that the slave is running a simple program:
(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
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:
MPI_...
: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_...
: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...
: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.
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 Read and 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
ParDeclareGlobalFunction(
string );
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.
[Up] [Previous] [Next] [Index]
ParGAP manual