Using PVM
F. Garacci

PVM (Parallel Virtual Machine) is a free software package wich allow to make parallel computing, on a heterogeneous collection of computers linked by a network, in a very easy way. You will find more information about it and how to download and setup it here :"http://www.epm.ornl.gov/pvm/pvm_home.html". The main operation mode of PVM is that you can, from an execution, send the execution of an other binary file in an other computer and, keeping its ID, communicate with it. The complete list of the PVM routine for C/C++ is avaible here :"http://nacphy.physics.orst.edu/PVM/ref/alpha.html"



1  Getting started

To get started with PVM, once it's installed, you will have to complete different tasks :

  1. Find out which computers are available. You can use any computer which fulfills the following requirements :
  2. Edit/create the file .rhosts in your home directory. Each computer that you want to use needs an entry in the .rhosts file consisting of the name of the computer and your login name on that machine, as shown here:
    penfret fgaracci
    capcoz fgaracci
    molotova fgaracci
    sounion fgaracci
    otway fgaracci
    korrigan fgaracci
    cygnusx1 fgaracci
    ophiucus fgaracci
    
  3. Create a directory named pvm3 in your home directory in which you'll create two symbolic links : include->/usr/local/pvm3/include/ and lib ->/usr/local/pvm3/lib/, and a directory named bin, then set environment variables :

2  The PVM console

The PVM console is an interface between you and your virtual machine; here you can add a host, delete a host, see the hosts statues, start or stop a process ... For a complete list of the available commands for the PVM console see: "http://nacphy.physics.orst.edu/PVM/ref/console.html". Here are the most usefull commands : To start the PVM console, once your environment variables are set, just type pvm in a xterm. Then you will see the prompt pvm> wich indicate that you're in the PVM console.




3  Programming in C/C++ with PVM

I advice you to create a directory for each architecture you'll use in your virtual machine in your $HOME/pvm3/bin directory then you'll put the correct binary file for all your program. To get the PVM code for a computer architechture, you can use the PVM function pvmgetarch.




4  What is the class Parallel?

The class Parallel is a class wich allow to use PVM in a more easy way, using ALP objects, and with an object oriented philosophy. Each object instantied from this class symbolize a task. There are four way to create an object : In order to send a task in a distant computer; you will just have to create a Parallel object with the good parameters and use the operators <<, >>. See below.

5  How to use it?

To use the class Parallel, there are two imperatives : Then you just have to include the Parallel.H file in all your sources in which you want to use the class Parallel.

6  The main concept

Once you have create some tasks, you will have to communicate between them. This is performed trought the PVM buffer: you just have to put your data in the buffer and send it to a target task. Then the target task have to recieve the buffer and operate on data. Be carefull: you have to take the data from the buffer in the same order that they were put in it. The operators '<<' and '>>' are overloaded for all the ALP object. They respectively put an object in the send buffer and take it from the recieved buffer.

7  A first exemple

This is the file Slave.C which will correspond the the slave task :
#include "parallel/PVM.H"
#include "linalg.H"
main()
{
  Parallel Slave;
  Parallel Master(MASTER);
  
  double t[]={1,2,3,4};
  VectStd > V(4,t);
  
  Slave.BuffInit();
  Slave>>V;
  Slave.Send(Master);
  
  Slave.Recieve(Master);
}


And here is the file Master.C which will correspond the the master task :
#include <iostream.h>
#include "parallel/PVM.H"
#include "linalg.H"
main()
{
  Parallel Master;

  cout<<"Master "<<Master.Tid()<<" sur : "<<Master.HostName()<<"\n";

  Parallel Slave1("Test_Slave");
  cout<<"Slave1 "<<Slave1.Tid()<<" sur : "<<Slave1.HostName()<<" fils
de  "<<Slave1.TidParent()<<"\n"; 

  VectStd<array1d<double> > V; 
 
  Master.Recieve(Slave1);
  Master<<V;
  cout<<"\nMaster a recu \n";
  cout<<V<<endl;
  Master.Kill(Slave1);
}
Here is the result of the execution of Master :
Master 262150 sur : molotova
Slave1 524290 sur : penfret fils de  262150

Master a recu 
[1, 2, 3, 4]

8  Implementation



parallel/PVM.H

class Parallel
Interface for the class Parallel wich allows to make parallel computation with ALP.
{
    public:
 
  // Return the name of the host of this task
  char* HostName();
 
 // Return the identificator of the task
  int Tid();

 // Return the identificator of the parent task
  int TidParent();
  
  // Return the number of computer in the parallel virtual machine
  int NbHosts();


  // the following methods put an array of simple type in the active
  // sent buffer 
  int Pack(int* IntArray,int Number=1, int Stride=1);
  int Pack(unsigned int* IntArray,int Number=1, int Stride=1);
  int Pack(double* DoubleArray,int Number=1, int Stride=1);
  int Pack(float* FloatArray,int Number=1, int Stride=1);
  int Pack(unsigned short* ShortArray,int Number=1, int Stride=1);
  int Pack(short* ShortArray,int Number=1, int Stride=1);
  int Pack(unsigned long* LongArray,int Number=1, int Stride=1);
  int Pack(long* LongArray,int Number=1, int Stride=1);
  int Pack(char* CharArray,int Number=1, int Stride=1);
  
  template 
  int Pack(T* ObjArray,int Number=1);

  // the following methods take an array of simple type from the active
  // recived buffer 
  int UnPack(int* IntArray,int Number=1, int Stride=1);
  int UnPack(unsigned int* IntArray,int Number=1, int Stride=1);
  int UnPack(double* DoubleArray,int Number=1, int Stride=1);
  int UnPack(float* FloatArray,int Number=1, int Stride=1);
  int UnPack(unsigned short* ShortArray,int Number=1, int Stride=1);
  int UnPack(short* ShortArray,int Number=1, int Stride=1);
  int UnPack(unsigned long* LongArray,int Number=1, int Stride=1);
  int UnPack(long* LongArray,int Number=1, int Stride=1);
  int UnPack(char* CharArray,int Number=1, int Stride=1);
 
  template 
  int UnPack(T* & ObjArray,int* Number);

  // Add Host to the virtual machine
  int AddHosts(char *HostName);

  // Add Hosts to the virtual machine
  int AddHosts(char **HostName,int NbHosts);

  // Add all the Hosts wich are in the .rhosts file, to the virtual machine
  int AddMaxHosts();

  // Delete Host to the virtual machine
  int DelHosts(char *HostName);

  // Delete Hosts to the virtual machine
  int DelHosts(char **HostName,int NbHosts);

  // Initialisation of the active send buffer
  void BuffInit();

  // Send the active buffer to the task designed by Target
  int Send(Parallel &Target,int Tag=1);
  
  // Receve from the task designed by Sender 
  int Recieve(Parallel &Sender,int Tag=1);

  int Recieve(int Tag=1);

  // Catch the output of the slaves tasks 
  int CatchOut(FILE *OutFile=stdout,int Option=14, int val=0);

  // Send the signal Sig to the task target
  int SendSig(Parallel &Target,int Sig);
  
  // kill the target task
  int Kill(Parallel &Target);

  // reset the task simbolized by the calling object, with the same
  // programme on the same host
  int Rebuild();

  // reset the task simbolized by the calling object, with the 
  // programme "Prog" on the same host
  int Rebuild(char* Prog);

  // reset the task simbolized by the calling object, with the same
  // programme on the host "Host"
  int Rebuild(char* Host);

  // reset the task simbolized by the calling object, with the 
  // programme "Prog" on the host "Host"
  int Rebuild(char* Prog, char* Host);

  // Default constructor, correspond to the current task
  Parallel();

  // Constructor of a task, wich will execute "Prog" on anyone of the
  // available machine
  Parallel(char* Prog);
  
  // Constructor of a task, wich will execute "Prog" on the machine "Host" 
  Parallel( char* Prog, char * Host);

  // Constructor of an object wich will symbolize the parent task
  Parallel(int Master);

  // Destructeur
  ~Parallel();

  private:
  
  // Name of the host
  char* hostName;
  char* prog;
  // Courrant task identification  
  int tid;
  // Parent task identification
  int tidParent;
  // Number of host of the virtual machine
  int nbHosts;
  // Number of different architectures in the virtual machine
  int nbArch;
};