pvm(3)
NAME
Pvm - Perl extension for the Parallel Virtual Machine
(PVM) Message Passing System
SYNOPSIS
use Pvm;
DESCRIPTION
The PVM message passing system enables a programmer to
configure a group of (possibly heterogenous) computers
connected by a network into a parallel virtual machine.
The system was developed by the University of Tennessee,
Oak Ridge National Laboratory and Emory University.
Using PVM, applications can be developed which spawns
parallel processes onto nodes in the virtual machine to
perform specific tasks. These parallel tasks can also
periodically exchange information using a set of message
passing functions developed for the system.
PVM applications have mostly been developed in the
scientific and engineering fields. However applications
for real-time and client/server systems can also be
developed. PVM simply provides a convenient way for
managing parallel tasks and communications without need
for rexec or socket level programming.
As a utility, PVM enables an organisation to leverage on
the computers already available for parallel processing.
Parallel applications can be started during non-peak hours
to utilise idle CPU cycles. Or dedicated workstation
clusters connected via a high performance network like ATM
can be used for high performance computing.
It is recommended that you read the PVM manual pages and
the book PVM: Parallel Virtual Machine, A users's guide
and tutorial for networked parallel computing. Both the
PVM system and the book can be obtained by email from
netlib@ornl.gov or anonymous ftp from netlib2.cs.utk.edu.
For the rest of this document we will provide a tutorial
introduction to developing PVM applications using perl.
The interface for some of the PVM functions have been
changed of course to give it a more perl-like feel.
Remember think perl think parallel! Good Luck!
Environment Variables
- After installing PVM on your computer, there are two
mandatory environment variables that have to be set in
your .login or .cshrc files; PVM_ROOT and PVM_ARCH.
PVM_ROOT points to the base of the PVM installation
directory, and PVM_ARCH specifies the architecture of the
computer on which PVM is running. An example of how this
can be set for csh is shown below, - setenv PVM_ROOT /usr/local/pvm3
setenv PVM_ARCH `$PVM_ROOT/lib/pvmgetarch` - Setting up your rsh permission
- In order for PVM applications to run, rsh permission has
to be enabled. This involves creating a .rhosts file in
your HOME directory containing, for each line, the host
and account name you wish to allow remote execution
privillages. An example .rhosts file to allow a PVM
application to remotely execute on the host onyx and prata
using the account edward is shown below,
onyx edward
prata edward- Configuring your parallel virtual machine
- Parallel process management and communications is handled
by a set of distributed deamons running on each of the
nodes of the virtual machine. The daemon executable,
pvmd, is started when a computer is added to the virtual
machine. A computer can be added to the virtual machine
either statically in a console program or using a
hostfile, or dynamically within the application code
itself. - The first method of configuring your virtual machine is to
use the console program $PVM_ROOT/lib/pvm. Run it from
the command prompt. The console program will first add
the local host into the virtual machine and display the
prompt pvm> - To add a host, eg onyx, as a node in your parallel virtual
machine, simply type
pvm> add onyx- To display the current virtual machine configuration type
pvm> conf- which will display node information pertaining to the host
name, host id, host architecture, relative speed and data
format. The console program has a number of other
commands which can be viewed by typing help. - The second method of configuring your virtual machine is
to use a hostfile. The hostfile is simply an ASCII text
file specifing the host names of the computers to be added
into your virtual machine. - Additional options may be also be defined for the nodes
pertaining to the working directory, execution path, login
name, alternative hostname etc. A simple example of a
hostfile is shown below.
* wd=$HOME/work ep=$HOME/bin
onyx
prata.nsrc.nus.sg
laksa ep=$HOME/perl5/bin- In the above example hostfile we are adding the hosts
onyx, prata.nsrc.nus.sg and laksa into the virtual
machine. We are also specifying the working directory, wd,
in which we want our application to run, and the execution
path, ep, in which we want PVM to look for executables. - The * in the first line defines a global option for all
the hosts specified after it. We can however provide an
option locally to over-ride this global option. This is
seen for the host laksa where we have specified its
execution path to be $HOME/perl5/bin instead of the
$HOME/bin. - The third method of configuring your virtual machine is to
call the functions Pvm::addhosts or Pvm::delhosts within
your application. You must still start your master pvmd
daemon first. This can be achieved by starting pvm and
typing quit or simply typing
echo quit | pvm- The PVM application can then be started where we can add
the hosts prata.nsrc.nus.sg and laksa by calling
Pvm::addhosts("prata.nsrc.nus.sg","laksa");- Or we can delete a host from our configuration by calling
Pvm::delhosts("laksa");- PVM also provides a function, Pvm::conf, to query the
configuration of the parallel virtual machine. An example
code to check the current configuration is shown below.
($info,@conf) = Pvm::conf ;
if ( $info == PvmOk ){foreach $node (@conf){print "host id = $node->{'hi_tid'}0;
print "host name = $node->{'hi_name'}0;
print "host architecture =$node->{'hi_arch'}0;
print "host speed = $node->{'hi_speed'}0;}- }
- Enrolling a task into PVM
- A task has to expilictly enroll into PVM in order for it
to be known by other PVM tasks. This can often be done by
the call $mytid = Pvm::mytid ; - where $mytid is the task id, TID, assigned by the PVM
system to the calling process. Note however that calling
any PVM function in a program will also enroll it into the
system. - Spawning parallel tasks
- A PVM application can spawn parallel tasks in your
parallel virtual machine. Assuming there is exists an
executable called client, we can spawn four client tasks
in our virtual machine by calling
($ntask,@tids) = Pvm::spawn("client",4);- For each of the four spawned processes, the PVM system
first allocates a host node and looks for the executable
in the execuation path of that host. If the executable is
found it is started. - The task which called the Pvm::spawn is known as the
parent task. The number of children tasks which are
actually spawned by Pvm::spawn is returned in the scalar
$ntask. The @tids array returns the task id, TID, of the
spawned children tasks which will be useful later for
communicating with them. A TID < 0 indicates a task
failure to spawn and can be used to determine the nature
of the problem. Eg.
foreach $tid (@tids){if ( $tid < 0 ){if ( $tid == PvmNoMem )warn "no memory ! 0;}else if ( $tid == PvmSysErr ){warn "pvmd not responding ! 0;} ...}- }
- For more sophisticated users, Pvm::spawn may be given
additional argument parameters to control how/where you
want a task to be spawned. For example, you can
specifically spawn client in the internet host
<onyx.nsrc.nus.sg> by calling
Pvm::spawn("client",1,Pvm- TaskHost,"onyx.nsrc.nus.sg");
- Or you can spawn client on host nodes only of a particular
architecture, say RS6K workstations, by calling
Pvm::spawn("client",4,PvmTaskArch,"RS6K");- Note that tasks which have been spawned by using
Pvm::spawn do not need to be explicitly enrolled into the
pvm system. - Exchanging messages between tasks
- Messages can be sent to a task enrolled into PVM by
specifying the example code sequence
Pvm::initsend ;
Pvm::pack(2.345,"hello dude");
Pvm::pack(1234);
Pvm::send($dtid,999);- In our example we first call Pvm::initsend to initialize
the internal PVM send buffer. We then call Pvm::buffer to
fill this buffer with a double (2.345), , a string ("hello
dude"), and an integer (1234). Having filled the send
buffer with the data that is to be sent, we call Pvm::send
to do the actual send to the task identifed by the TID
$dtid. We also label the sending message to disambiguate
it with other messages with a tag. This is done with the
999 argument in Pvm::send function. - For the destination task, we can receive the message sent
by performing a blocking receive with the function
Pvm::recv. A code sequence for the above example on the
recipent end will be
if ( Pvm::recv >= 0 ){$int_t = Pvm::unpack ;
($double_t,$str_t) = Pvm::unpack ;- }
- Note that we must unpack the message in the reverse order
in which we packed our message. In our example Pvm::recv
will receive any message sent to it. In order to
selectively receive a message, we could specify the TID of
the source task and the message tag. For example,
$tag = 999;
Pvm::recv($stid,$tag) ;- Other message passing functions that you may find useful
are Pvm::psend, Pvm::trecv, Pvm::nrecv and Pvm::precv. - Parallel I/O
- Note that the file descriptors in a parent task are not
inherented in the spawned children tasks unlike fork. By
default any file I/O will be performed in the working
directory specified in the hostfile if no absolute path
was provided for the opened file. If no working directory
is specified, the default is the $HOME directory. For
directories which are not NFS mounted, this would mean
that each task performs its own separate I/O. - In the case of tty output, tasks which are not started
from the command prompt will have their stdout and stderr
directed to the file pvml.<uid>. This may be redirected
to a parent task by calling
Pvm::catchout;- for stdout or
Pvm::catchout(stderr);- for stderr. You can direct the stdout or stderr output
of a task to another TID , other then its parent, by
calling
Pvm::setopt(PvmOutTid,$tid);- Incorporating fault tolerance
- The function Pvm::notify can be used to incorporate some
fault tolerance into your PVM application. You may use it
to ask the PVM to monitor the liveliness of a set of hosts
or tasks during the execution of a PVM application. For
example you can instrument your application to monitor 3
tasks with TID $task1, $task2, and $task3, by using the
code segments
@monitor = ($task1,$task2,$task3);
Pvm::notify(PvmTaskExit,999,@monitor_task);
...- if ( Pvm::probe(-1,999) ){
$task = Pvm::recv_notify ;
print "Oops! task $task has failed ... 0 ; - }
- If either $task1, $task2 or $task3 fails, the
notification will take the form of a single message with
the tag 999. The message content will inform you of the
TID of the failed task. - A similar scheme may be employed for the notification of
host failures in your parallel virtual machine. - Client/Server example
- Client:
use Pvm;
use File::Basename;
...- # Look for server tid and assume
# server name is 'service_provider' - @task_list = Pvm::tasks ;
foreach $task (@task_list){$a_out = $task->{'ti_a_out'} ;
$base = basename $a_out ;
if ( $base eq 'service_provider' )$serv_tid = $task->{'ti_tid'} ;}# This is just one way (not necessarily the
# best) of getting a server tid.
# You could do the same thing by reading
# the server tid posted in a file....# send request for service
Pvm::send($serv_tid,$REQUEST);# receive service from server
Pvm::recv(-1,$RESPONSE);
@service_packet = Pvm::unpack ;
... - Server:
while(1){...if ( Pvm::probe(-1,$REQUEST) ){
# a service request has arrived !
$bufid = Pvm::recv ;
($info,$bytes,$tag,$stid) = Pvm::bufinfo($bufid) ;if ( fork == 0 ){# fork child process to handle service
...# provide service
Pvm::initsend ;
Pvm::pack(@service);
Pvm::send($stid,$RESPONSE);# exit child process
exit ;}}
...- }
- PVM groups
- The PVM dynamic group functions have not been ported to
perl yet. These functions provide facilities for
collecting processes under a single group label, and
applying aggregate operations onto them. Examples of
these functions are Pvm::barrier, Pvm::reduce, Pvm::bcast
etc. One of our concerns is that these group functions
may be changed or augmented in the future releases of PVM
3.4*. A decision for porting the group functions will be
made after PVM 3.4 has been released.
FUNCTIONS
- Pvm::addhosts
Adds one or more host names to a parallel virtual machine.
Eg. - $info = Pvm::addhosts(@host_list) ;
- Pvm::bufinfo
Returns information about the requested message buffer.
Eg.
($info,$bytes,$tag,$tid) = Pvm::bufinfo($bufid);- Pvm::catchout
Catches output from children tasks. Eg.
# Pvm::catchout(stdout);
$bufid = Pvm::catchout;- Pvm::config
Returns information about the present virtual machine
configuration. Eg.
($info,@host_ref_list) = Pvm::config ;- Pvm::delhosts
Deletes one or more hosts from the virtual machine. Eg.
$info = Pvm::delhosts(@host_list);- Pvm::exit
Tells the local PVM daemon that the process is leaving.
Eg.
$info = Pvm::exit ;- Pvm::freebuf
Disposes of a message buffer. Eg.
$info = Pvm::freebuf($bufid);- Pvm::getopt
Shows various libpvm options. Eg.
$val = Pvm::getopt(PvmOutputTid);
$val = Pvm::getopt(PvmFragSize);- Pvm::getrbuf
Returns the message buffer identifier for the active
receive buffer. Eg.
$bufid = Pvm::getrbuf ;- Pvm::getsbuf
Returns the message buffer identifier for the active send
buffer. Eg.
$bufid = Pvm::getsbuf ;- Pvm::halt
Shuts down the entire PVM system. Eg.
$info = Pvm::halt ;- Pvm::hostsync
Gets time-of-day clock from PVM host. Eg.
($info,$remote_clk,$delta) = Pvm::hostsync($host)- ;
- where delta is the time-of-day equivalent to local_clk remote_clk.
- Pvm::initsend
Clears default send buffer and specifies message encoding.
Eg.
# Pvm::initsend(PvmDataDefault) ;
$bufid = Pvm::initsend- Pvm::kill
Terminates a specified PVM process.
$info = Pvm::kill($tid);- Pvm::mcast
Multicast the data in the active message buffer to a set
of tasks. Eg.
$info = Pvm::mcast(@tid_list,$tag);- Pvm::mkbuf
Creates a new message buffer. Eg.
# Pvm::mkbuf(PvmDataDefault);
$bufid = Pvm::mkbuf ;- $bufid = Pvm::mkbuf(PvmDataRaw);
- Pvm::mstat
Returns the status of a host in the virtual machine. Eg.
$status = Pvm::mstat($host);- Pvm::mytid
Returns the tid of the calling process.
$mytid = Pvm::mytid ;- Pvm::notify
Requests notification of PVM events. Eg.
$info = Pvm::notify(PvmHostDelete,999,$host_list);- Pvm::nrecv
Nonblocking receive. Eg.
# Pvm::nrecv(-1,-1);
$bufid = Pvm::nrecv ;- # Pvm::nrecv($tid,-1);
$bufid = Pvm::nrecv($tid) ; - $bufid = Pvm::nrecv($tid,$tag) ;
- Pvm::pack
Packs active message buffer with data. Eg.
$info = Pvm::pack(@data_list);- Pvm::parent
Returns the tid of the process that spawned the calling
process. Eg.
$tid = Pvm::parent ;- Pvm::perror
Prints the error status of the las PVM call.
$info = Pvm::perror($msg);- Pvm::precv
Receives a message directly into a buffer.
# Pvm::precv(-1,-1);
@recv_buffer = Pvm::precv ;- # Pvm::precv($tid,-1);
@recv_buffer = Pvm::precv($tid); - @recv_buffer = Pvm::precv($tid,$tag);
- Note that the current limit for the receive buffer is 100
KBytes. - Pvm::probe
Checks whether a message has arrived. Eg.
# Pvm::probe(-1,-1);
$bufid = Pvm::probe ;- # Pvm::probe($tid,-1);
$bufid = Pvm::probe($tid); - $bufid = Pvm::probe($tid,$tag);
- Pvm::psend
Packs and sends data in one call. Eg.
$info = Pvm::psend($tid,$tag,@send_buffer);- Pvm::pstat
Returns the status of the specified PVM process. Eg.
$status = Pvm::pstat($tid);- Pvm::recv
Receives a message. Eg.
# Pvm::recv(-1,-1);
$bufid = Pvm::recv ;- # Pvm::recv($tid,-1);
$bufid = Pvm::recv($tid) ; - $bufid = Pvm::recv($tid,$tag);
- Pvm::recvf
Redefines the comparison function used to accept messages.
Eg.
Pvm::recvf(new_foo);- Pvm::recv_notify
Receives the notification message initiated by
Pvm::notify. This should be preceded by a Pvm::probe.
Eg.
if ( Pvm::probe(-1,$notify_tag) ){$message = Pvm::recv_notify ;- }
- Pvm::recvf_old
Resets the comparison function for accepting messages to
the previous method before a call to Pvm::recf. - Pvm::reg_hoster
Registers this task as responsible for adding new PVM
hosts. Eg.
$info = Pvm::reg_hoster ;- Pvm::reg_rm
Registers this task as a PVM resource manager. Eg.
$info = Pvm::reg_rm ;- Pvm::reg_tasker
Registers this task as responsible for starting new PVM
tasks. Eg.
$info = Pvm::reg_tasker ;- Pvm::send
Send the data in the active message buffer. Eg.
# Pvm::send(-1,-1);
$info = Pvm::send ;- # Pvm::send($tid,-1);
$info = Pvm::send($tid); - $info = Pvm::send($tid,$tag);
- Pvm::sendsig
Sends a signal to another PVM process. Eg.
use POSIX qw(:signal_h);
...- $info = Pvm::sendsig($tid,SIGKILL);
- Pvm::setopt
Sets various libpvm options. Eg.
$oldval=Pvm::setopt(PvmOutputTid,$val);- $oldval=Pvm::setopt(PvmRoute,PvmRouteDirect);
- Pvm::setrbuf
Switches the active receive buffer and saves the previous
buffer. Eg.
$oldbuf = Pvm::setrbuf($bufid);- Pvm::setsbuf
Switches the active send buffer. Eg.
$oldbuf = Pvm::setsbuf($bufid);- Pvm::spawn
Starts new PVM processes. Eg.
# Pvm::spawn("compute.pl",4,PvmTaskDefault,"");
($ntask,@tid_list) = Pvm::spawn("compute.pl",4);- ($ntask,@tid_list) = Pvm::spawn("com
- pute.pl",4,PvmTaskHost,"onyx");
- Pvm::tasks
Returns information about the tasks running on the virtual
machine. Eg.
# Pvm::tasks(0); Returns all tasks
($info,@task_list) = Pvm::tasks ;- # Returns only for task $tid
($info,@task_list) = Pvm::tasks($tid) ; - Pvm::tidtohost
Returns the host ID on which the specified task is
running. Eg.
$dtid = Pvm::tidtohost($tid);- Pvm::trecv
Receive with timeout. Eg.
# Pvm::trecv(-1,-1,1,0); time out after 1 sec
$bufid = Pvm::trecv ;- # time out after 2*1000000 + 5000 usec
$bufid = Pvm::trecv($tid,$tag,2,5000); - Pvm::unpack
Unpacks the active receive message buffer. Eg.
@recv_buffer = Pvm::unpack ;
AUTHOR
Edward Walker, edward@nsrc.nus.sg, National Supercomputing
Research Centre