#% -*- mode: tm; mode: fold -*-

#%{{{Macros

#i linuxdoc.tm
#d it#1 <it>$1</it>

#d slang \bf{S-lang}
#d exmp#1 \tt{$1}
#d var#1 \tt{$1}

#d ivar#1 \tt{$1}
#d ifun#1 \tt{$1}
#d cvar#1 \tt{$1}
#d cfun#1 \tt{$1}
#d svar#1 \tt{$1}
#d sfun#1 \tt{$1}
#d icon#1 \tt{$1}

#d chapter#1 <chapt>$1<p>
#d preface <preface>
#d tag#1 <tag>$1</tag>

#d function#1 \sect{<bf>$1</bf>\label{$1}}<descrip>
#d variable#1 \sect{<bf>$1</bf>\label{$1}}<descrip>
#d function_sect#1 \sect{$1}
#d begin_constant_sect#1 \sect{$1}<itemize>
#d constant#1 <item><tt>$1</tt>
#d end_constant_sect </itemize>

#d synopsis#1 <tag> Synopsis </tag> $1
#d keywords#1 <tag> Keywords </tag> $1
#d usage#1 <tag> Usage </tag> <tt>$1</tt>
#d description <tag> Description </tag>
#d example <tag> Example </tag>
#d notes <tag> Notes </tag>
#d seealso#1 <tag> See Also </tag> <tt>\linuxdoc_list_to_ref{$1}</tt>
#d done </descrip><p>
#d -1 <tt>-1</tt>
#d 0 <tt>0</tt>
#d 1 <tt>1</tt>
#d 2 <tt>2</tt>
#d 3 <tt>3</tt>
#d 4 <tt>4</tt>
#d 5 <tt>5</tt>
#d 6 <tt>6</tt>
#d 7 <tt>7</tt>
#d 8 <tt>8</tt>
#d 9 <tt>9</tt>
#d NULL <tt>NULL</tt>
#d documentstyle book

#d iflatex#2 <#if output=latex2e>$1</#if><#unless output=latex2e>$2</#unless>
#d ifhtml#2 <#if output=html>$1</#if><#unless output=html>$2</#unless>
 
#%}}}

#d module#1 \tt{$1}
#d file#1 \tt{$1}
#d slang-documentation \
 \url{http://www.s-lang.org/doc/html/slang.html}{S-Lang documentation}

#d pvm-documentation \url{http://www.csm.ornl.gov/pvm/}{PVM documentation}

#d modules_home http://space.mit.edu/cxc/software/slang/modules
#d hello_master_url \modules_home/pvm/examples/hello_master
#d hello_slave_url \modules_home/pvm/examples/hello_slave
#d master_url \modules_home/pvm/examples/master
#d slave_url \modules_home/pvm/examples/slave

#d hello_master \ifhtml{\url{\hello_master_url}{hello_master}}{hello_master}
#d hello_slave \ifhtml{\url{\hello_master_url}{hello_slave}}{hello_slave}
#d master \ifhtml{\url{\master_url}{master}}{master}
#d slave \ifhtml{\url{\master_url}{slave}}{slave}

\linuxdoc
\begin{\documentstyle}

\title S-Lang PVM Module Reference
\author John C. Houck, \tt{houck@space.mit.edu}
\date \__today__

\toc

\chapter{Introduction to the PVM Module}

 PVM (Parallel Virtual Machine) is a software package which
 permits a heterogeneous collection of Unix and/or Windows
 computers, connected by a network, to be used as a single
 large parallel computer.  The \module{PVM} module provides a
 \slang interface to this package. By performing distributed
 computations with \slang one can make better use of available
 computer resources yet still retain the advantages of
 programming in an interpreted language.

 This document briefly describes how to use the \slang
 interface to \module{PVM}.  It assumes that the reader is
 already familiar with the PVM package itself.
 
 For complete details on obtaining, installing and using the
 PVM package, see the \pvm-documentation.  Note that, once the
 PVM package is properly installed on your computer, the PVM
 \exmp{man} pages will provide detailed documentation on all
 the PVM library functions.  
 
 Although the \slang \module{PVM} module functions often have
 slightly different interfaces, the differences are usually
 minor so the PVM documentation is quite helpful.  Because
 the \slang interface is not yet fully documented, it will
 be necessary to consult the \module{PVM} documentation directly
 to make full use of the \slang \module{PVM} module.
 
 Because PVM processes require running programs on remote
 hosts, it is necessary to provide each host with the full path
 to the relevant executables.  To simplify this process, it may
 be useful to create a directory, e.g.\exmp{$HOME/bin/PVM}, on
 every host and put relevant executables in that directory so
 that the same relative path will work on all machines.  This
 PVM path may be specified in the \exmp{$HOME/.pvmhosts}
 configuration file; for a detailed description of the contents
 of this file, see the \exmp{pvmd} man page.
 
 The usage examples discussed in this manual assume that the
 PVM has already been initialized by running a command such as
#v+
  unix> pvm ~/.pvmhosts
#v-
 This starts the PVM \it{console} and also starts the PVM
 daemon, \exmp{pvmd}, on each remote host.  This daemon runs
 all PVM slave processes and handles all communications with
 the parent process and the rest of the PVM.
 
 The execution environment of the PVM slave processes is
 inherited from the corresponding \exmp{pvmd} process which, in
 turn, is inherited from the parent process which started the
 PVM \it{console}.  However, it is sometimes useful to
 configure the environment of the remote \exmp{pvmd} process
 using a startup script, \exmp{$HOME/.pvmprofile}. This is a
 Bourne shell script which, if present, is run when \exmp{pvmd}
 is started.  For a detailed description of the contents of
 this file, see the \exmp{pvmd} man page.
 
\chapter{Using the PVM Module}

 To use the \module{PVM} module in a \slang script, it is first
 necessary to make the functions in the package known to the
 interpreter via
#v+
    () = evalfile ("pvm");
#v-
 or, if the application embedding the interpreter supports the
 \sfun{require} function,
#v+
    require ("pvm");
#v-
 may be used.  If there is a namespace conflict between symbols in the
 script and those defined in the module, it may be necessary to load
 the PVM package into a namespace, e.g.,
#v+
   () = evalfile ("pvm", "p");
#v-
 will place the PVM symbols into a namespace called \exmp{p}.

 Once the PVM module has been loaded, the functions it defines
 may be used in the usual way, e.g.,
#v+
    require ("pvm");
        .
        .
    variable master_tid = pvm_mytid ();
#v-
 where \ifun{pvm_mytid} is the PVM function which returns the
 task identifier of the calling process.

\chapter{Examples}

 This section presents examples of two alternate methods of
 using the PVM module.  The source code for these examples is
 included in the \module{PVM} module source code distribution
 in the \file{examples} subdirectory. The first method uses PVM
 library routines to manage a simple distributed application.
 The second method uses the higher-level master-slave
 interface.  This interface can provide a high degree of
 tolerance to failure of slave machines which proves useful in
 long-running distributed applications.

\sect{Example 1:  A Simple \it{Hello World} Program}

 In programming language tutorials, the first example is
 usually a program which simply prints out a message such as
 \it{Hello World} and then exits.  The intent of such a trivial
 example is to illustrate all the steps involved in writing and
 running a program in that language.

 To write a \it{Hello World} program using the PVM module, we will
 write two programs, the master (\hello_master), and the
 slave (\hello_slave).  The master process will spawn a
 slave process on different host and then wait for a message
 from that slave process.  When the slave runs, it sends a
 message to the master, or parent, and then exits. For the
 purpose of this example, we will assume that the PVM consists
 of two hosts, named \exmp{vex} and \exmp{pirx}, and that the
 slave process will run on \exmp{pirx}.

\sect1{The \file{hello_master} program}

 First, consider the master process, \hello_master.
 Conceptually, it must specify the full path to the slave
 executable and then send that information to the slave host
 (\exmp{pirx}).  For this example, we assume that the
 master and slave executables are in the same directory and
 that the master process is started in that directory. With
 this assumption, we can construct the path to the slave
 executable using the \sfun{getcwd} and \sfun{path_concat}
 functions. We then send this information to the slave host
 using the \ifun{pvm_spawn} function:
#v+
   path = path_concat (getcwd(), "hello_slave");
   slave_tid = pvm_spawn (path, PvmTaskHost, "pirx", 1);
#v-
 The first argument to \ifun{pvm_spawn} specifies the full path
 to the slave executable.  The second argument is a bit mask
 specifying options associated with spawning the slave process.
 The \icon{PvmTaskHost} option indicates that the slave process
 is to be started on a specific host.  The third argument gives
 the name of the slave host and the last argument indicates how
 many copies of this process should be started. The return
 value of \ifun{pvm_spawn} is an array of task identifiers for
 each of the slave processes; negative values indicate that an
 error occurred.

 Having spawned the \hello_slave process on \exmp{pirx},
 the master process calls the \ifun{pvm_recv} function to
 receive a message from the slave.
#v+
   bufid = pvm_recv (-1, -1);
#v-
 The first argument to \ifun{pvm_recv} specifies the task
 identifier of the slave process expected to send the message
 and the second argument specifies the type of message that is
 expected.  A slave task identifier \-1 means that a
 message from any slave will be accepted.  Similarly, a message
 identifier of \-1 means that any type of message will be
 accepted.  In this example, we could have specified
 the slave task id and the message identifier explicitly:
#v+
  bufid = pvm_recv (slave_tid, 1);
#v-
 When a suitable message is received, the contents of the
 message are stored in a PVM buffer and \ifun{pvm_recv} returns
 the buffer identifier which may be used by the PVM application
 to retrieve the contents of the buffer.

 Retrieving the contents of the buffer normally requires
 knowing the format in which the information is stored. In this
 case, because we accepted all types of messages from the
 slave, we may need to examine the message buffer to find out
 what kind of message was actually recieved. The
 \ifun{pvm_bufinfo} function is used to obtain information
 about the contents of the buffer.
#v+
   (,msgid,) = pvm_bufinfo (bufid);
#v-
 Given the buffer identifier, \ifun{pvm_bufinfo} returns the
 number of bytes, the message identifier and the task identifer
 sending the message.

 Because we know that the slave process sent a single object of
 \svar{Struct_Type}, we retrieve it by calling the
 \ifun{pvm_recv_obj} function.
#v+
   variable obj = pvm_recv_obj();
   vmessage ("%s says %s", obj.from, obj.msg);
#v-
 This function is not part of the PVM package but is a higher
 level function provided by the \module{PVM} module.  It
 simplifies the process of sending \slang objects between hosts
 by handling some of the bookkeeping required by the lower
 level PVM interface.  Having retrieved a \slang object from
 the message buffer, we can then print out the message.
 Running \hello_master, we see:
#v+
  vex> ./hello_master
  pirx says Hello World
#v-
 Note that before exiting, all PVM processes should call the
 \ifun{pvm_exit} function to inform the \file{pvmd} daemon of
 the change in PVM status.
#v+
   pvm_exit();
   exit(0);
#v-
 At this point, the script may exit normally.

\sect1{The \file{hello_slave} program}

 Now, consider the slave process, \hello_slave.
 Conceptually, it must first determine the location of its
 parent process, then create and send a message to that
 process.

 The task identifier of the parent process is obtained using
 the \ifun{pvm_parent} function.
#v+
   variable ptid = pvm_parent();
#v-
 For this example, we will send a message consisting of a
 \slang structure with two fields, one containing the name of
 the slave host and the other containing the string
 \exmp{"Hello World"}.

 We use the \ifun{pvm_send_obj} function to send this this
 message because it automatically handles packaging all the
 separate structure fields into a PVM message buffer and also
 sends along the structure field names and data types so that
 the structure can be automatically re-assembled by the
 receiving process. This makes it possible to write code which
 transparently sends \slang objects from one host to
 another. To create and send the structure:
#v+
   variable s = struct {msg, from};
   s.msg = "Hello World";
   s.from = getenv ("HOST");

   pvm_send_obj (ptid, 1, s);
#v-
 The first argument to \ifun{pvm_send_obj} specifies the task
 identifier of the destination process, the second argument is
 a message identifier which is used to indicate what kind of
 message has been sent.  The remaining arguments contain the
 data objects to be included in the message.

 Having sent a message to the parent process, the slave process
 then calls \ifun{pvm_exit} to inform the \file{pvmd} daemon
 that its work is complete.  This allows \file{pvmd} to notify
 the parent process that a slave process has exited. The slave
 then exits normally.

\sect{Example 2:  Using the Master-Slave Interface}

 The \module{PVM} module provides a higher level interface to
 support the master-slave paradigm for distributed
 computations. The symbols associated with this interface have
 the \exmp{pvm_ms} prefix to distinguish them from those
 symbols associated with the PVM package itself.

 The \exmp{pvm_ms} interface provides a means for handling
 computations which consist of a predetermined list of tasks
 which can be performed by running arbitrary slave processes
 which take command-line arguments. The interface provides a
 high degree of robustness, allowing one to add or delete hosts
 from the PVM while the distributed process is running and also
 ensuring that the task list will be completed even if one or
 more slave hosts fail (e.g. crash) during the computation.
 Experience has shown that this failure tolerance is
 surprisingly important.  Long-running distributed computations
 experience failure of one or more hosts with surprising
 frequency and it is essential that such failures do not
 require restarting the entire distributed computation from the
 beginning.

 Scripts using this interface must initialize it by loading
 the \exmp{pvm_ms} package via, e.g.
#v+
      require ("pvm_ms");
#v-
 As an example of how to use this interface, we examine the
 scripts \master and \slave.

\sect1{The \file{master} program}

 The \master script first builds a list of tasks each
 consisting of an array of strings which provide the command
 line for each slave process that will be spawned on the PVM.
 For this simple example, the same command line will be
 executed a specified number of times. First, the script
 constructs the path to the \slave executable,
 (\var{Slave_Pgm}), and then the command line (\var{Cmd}), that
 each \slave instance will invoke.  Then the array of
 tasks is constructed:

#v+
 variable pgm_argvs = Array_Type[N];
 variable pgm_argv = [Slave_Pgm, Cmd];

 pgm_argvs[*] = pgm_argv;
#v-

 The distribution of these tasks across the available PVM is
 automatically handled by the \exmp{pvm_ms} interface. The
 interface will simultaneously start as many tasks as possible
 up to some maximum number of processes per host. Here we
 specify that a maximum of two processes per host may run
 simultaneously and then submit the list of tasks to the PVM:

#v+
   pvm_ms_set_num_processes_per_host (2);
   exit_status = pvm_ms_run_master (pgm_argvs);
#v-

 As each slave process is completed, its exit status is
 recorded along with any messages printed to \var{stdout}
 during the execution. When the entire list of tasks is
 complete, an array of structures is returned containing status
 information for each task that was executed. In this example,
 the \master process simply prints out this information.

\sect1{The \file{slave} program}

 The \slave process in this example is relatively simple.
 Its command line arguments provide the task to be completed.
 These arguments are then passed to \ifun{pvm_ms_run_slave}
#v+
  pvm_ms_run_slave (__argv[[1:]]);
#v-
 which spawns a subshell, runs the specified command,
 communicates the task completion status to the parent process
 and exits.

\chapter{Master-Slave Function Reference}

#i pvm_msfuns.tm

\chapter{PVM Module Function Reference}

#i pvmfuns.tm

\chapter{Module Symbols Lacking Documentation}

Although many more low-level PVM intrinsic functions are
provided by the S-Lang module, not all of S-Lang interfaces
have been documented. See the PVM documentation for information
on the following functions:

#v+
#i pvm_undoc.tm
#v-

Similarly, the following PVM intrinsic constants are provided
by the S-Lang module but are documented only through the
PVM documentation.

#v+
#i pvm_undoc_const.tm
#v-

\end{\documentstyle}
