File: pvm-3.html

package info (click to toggle)
slpvm 0.1.5-11
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 1,072 kB
  • ctags: 254
  • sloc: sh: 2,624; ansic: 1,012; makefile: 154
file content (315 lines) | stat: -rw-r--r-- 12,707 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
 <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.21">
 <TITLE> S-Lang PVM Module Reference: Examples</TITLE>
 <LINK HREF="pvm-4.html" REL=next>
 <LINK HREF="pvm-2.html" REL=previous>
 <LINK HREF="pvm.html#toc3" REL=contents>
</HEAD>
<BODY>
<A HREF="pvm-4.html">Next</A>
<A HREF="pvm-2.html">Previous</A>
<A HREF="pvm.html#toc3">Contents</A>
<HR>
<H2><A NAME="s3">3.</A> <A HREF="pvm.html#toc3">Examples</A></H2>


<P>This section presents examples of two alternate methods of
using the PVM module.  The source code for these examples is
included in the <CODE>PVM</CODE> module source code distribution
in the <CODE>examples</CODE> 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.</P>

<H2><A NAME="ss3.1">3.1</A> <A HREF="pvm.html#toc3.1">Example 1:  A Simple <I>Hello World</I> Program</A>
</H2>


<P>In programming language tutorials, the first example is
usually a program which simply prints out a message such as
<I>Hello World</I> 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.</P>
<P>To write a <I>Hello World</I> program using the PVM module, we will
write two programs, the master (
<A HREF="http://space.mit.edu/cxc/software/slang/modules/pvm/examples/hello_master">hello_master</A>), and the
slave (
<A HREF="http://space.mit.edu/cxc/software/slang/modules/pvm/examples/hello_master">hello_slave</A>).  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 <CODE>vex</CODE> and <CODE>pirx</CODE>, and that the
slave process will run on <CODE>pirx</CODE>.</P>

<H3>The <CODE>hello_master</CODE> program</H3>


<P>First, consider the master process, 
<A HREF="http://space.mit.edu/cxc/software/slang/modules/pvm/examples/hello_master">hello_master</A>.
Conceptually, it must specify the full path to the slave
executable and then send that information to the slave host
(<CODE>pirx</CODE>).  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 <CODE>getcwd</CODE> and <CODE>path_concat</CODE>
functions. We then send this information to the slave host
using the <CODE>pvm_spawn</CODE> function:
<BLOCKQUOTE><CODE>
<PRE>
   path = path_concat (getcwd(), "hello_slave");
   slave_tid = pvm_spawn (path, PvmTaskHost, "pirx", 1);
</PRE>
</CODE></BLOCKQUOTE>

The first argument to <CODE>pvm_spawn</CODE> specifies the full path
to the slave executable.  The second argument is a bit mask
specifying options associated with spawning the slave process.
The <CODE>PvmTaskHost</CODE> 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 <CODE>pvm_spawn</CODE> is an array of task identifiers for
each of the slave processes; negative values indicate that an
error occurred.</P>
<P>Having spawned the 
<A HREF="http://space.mit.edu/cxc/software/slang/modules/pvm/examples/hello_master">hello_slave</A> process on <CODE>pirx</CODE>,
the master process calls the <CODE>pvm_recv</CODE> function to
receive a message from the slave.
<BLOCKQUOTE><CODE>
<PRE>
   bufid = pvm_recv (-1, -1);
</PRE>
</CODE></BLOCKQUOTE>

The first argument to <CODE>pvm_recv</CODE> 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 <CODE>-1</CODE> means that a
message from any slave will be accepted.  Similarly, a message
identifier of <CODE>-1</CODE> 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:
<BLOCKQUOTE><CODE>
<PRE>
  bufid = pvm_recv (slave_tid, 1);
</PRE>
</CODE></BLOCKQUOTE>

When a suitable message is received, the contents of the
message are stored in a PVM buffer and <CODE>pvm_recv</CODE> returns
the buffer identifier which may be used by the PVM application
to retrieve the contents of the buffer.</P>
<P>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
<CODE>pvm_bufinfo</CODE> function is used to obtain information
about the contents of the buffer.
<BLOCKQUOTE><CODE>
<PRE>
   (,msgid,) = pvm_bufinfo (bufid);
</PRE>
</CODE></BLOCKQUOTE>

Given the buffer identifier, <CODE>pvm_bufinfo</CODE> returns the
number of bytes, the message identifier and the task identifer
sending the message.</P>
<P>Because we know that the slave process sent a single object of
<CODE>Struct_Type</CODE>, we retrieve it by calling the
<CODE>pvm_recv_obj</CODE> function.
<BLOCKQUOTE><CODE>
<PRE>
   variable obj = pvm_recv_obj();
   vmessage ("%s says %s", obj.from, obj.msg);
</PRE>
</CODE></BLOCKQUOTE>

This function is not part of the PVM package but is a higher
level function provided by the <CODE>PVM</CODE> module.  It
simplifies the process of sending <B>S-lang</B> objects between hosts
by handling some of the bookkeeping required by the lower
level PVM interface.  Having retrieved a <B>S-lang</B> object from
the message buffer, we can then print out the message.
Running 
<A HREF="http://space.mit.edu/cxc/software/slang/modules/pvm/examples/hello_master">hello_master</A>, we see:
<BLOCKQUOTE><CODE>
<PRE>
  vex&gt; ./hello_master
  pirx says Hello World
</PRE>
</CODE></BLOCKQUOTE>

Note that before exiting, all PVM processes should call the
<CODE>pvm_exit</CODE> function to inform the <CODE>pvmd</CODE> daemon of
the change in PVM status.
<BLOCKQUOTE><CODE>
<PRE>
   pvm_exit();
   exit(0);
</PRE>
</CODE></BLOCKQUOTE>

At this point, the script may exit normally.</P>

<H3>The <CODE>hello_slave</CODE> program</H3>


<P>Now, consider the slave process, 
<A HREF="http://space.mit.edu/cxc/software/slang/modules/pvm/examples/hello_master">hello_slave</A>.
Conceptually, it must first determine the location of its
parent process, then create and send a message to that
process.</P>
<P>The task identifier of the parent process is obtained using
the <CODE>pvm_parent</CODE> function.
<BLOCKQUOTE><CODE>
<PRE>
   variable ptid = pvm_parent();
</PRE>
</CODE></BLOCKQUOTE>

For this example, we will send a message consisting of a
<B>S-lang</B> structure with two fields, one containing the name of
the slave host and the other containing the string
<CODE>"Hello World"</CODE>.</P>
<P>We use the <CODE>pvm_send_obj</CODE> 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 <B>S-lang</B> objects from one host to
another. To create and send the structure:
<BLOCKQUOTE><CODE>
<PRE>
   variable s = struct {msg, from};
   s.msg = "Hello World";
   s.from = getenv ("HOST");

   pvm_send_obj (ptid, 1, s);
</PRE>
</CODE></BLOCKQUOTE>

The first argument to <CODE>pvm_send_obj</CODE> 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.</P>
<P>Having sent a message to the parent process, the slave process
then calls <CODE>pvm_exit</CODE> to inform the <CODE>pvmd</CODE> daemon
that its work is complete.  This allows <CODE>pvmd</CODE> to notify
the parent process that a slave process has exited. The slave
then exits normally.</P>

<H2><A NAME="ss3.2">3.2</A> <A HREF="pvm.html#toc3.2">Example 2:  Using the Master-Slave Interface</A>
</H2>


<P>The <CODE>PVM</CODE> module provides a higher level interface to
support the master-slave paradigm for distributed
computations. The symbols associated with this interface have
the <CODE>pvm_ms</CODE> prefix to distinguish them from those
symbols associated with the PVM package itself.</P>
<P>The <CODE>pvm_ms</CODE> 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.</P>
<P>Scripts using this interface must initialize it by loading
the <CODE>pvm_ms</CODE> package via, e.g.
<BLOCKQUOTE><CODE>
<PRE>
      require ("pvm_ms");
</PRE>
</CODE></BLOCKQUOTE>

As an example of how to use this interface, we examine the
scripts 
<A HREF="http://space.mit.edu/cxc/software/slang/modules/pvm/examples/master">master</A> and 
<A HREF="http://space.mit.edu/cxc/software/slang/modules/pvm/examples/master">slave</A>.</P>

<H3>The <CODE>master</CODE> program</H3>


<P>The 
<A HREF="http://space.mit.edu/cxc/software/slang/modules/pvm/examples/master">master</A> 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 
<A HREF="http://space.mit.edu/cxc/software/slang/modules/pvm/examples/master">slave</A> executable,
(<CODE>Slave_Pgm</CODE>), and then the command line (<CODE>Cmd</CODE>), that
each 
<A HREF="http://space.mit.edu/cxc/software/slang/modules/pvm/examples/master">slave</A> instance will invoke.  Then the array of
tasks is constructed:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
 variable pgm_argvs = Array_Type[N];
 variable pgm_argv = [Slave_Pgm, Cmd];

 pgm_argvs[*] = pgm_argv;
</PRE>
</CODE></BLOCKQUOTE>
</P>
<P>The distribution of these tasks across the available PVM is
automatically handled by the <CODE>pvm_ms</CODE> 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:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
   pvm_ms_set_num_processes_per_host (2);
   exit_status = pvm_ms_run_master (pgm_argvs);
</PRE>
</CODE></BLOCKQUOTE>
</P>
<P>As each slave process is completed, its exit status is
recorded along with any messages printed to <CODE>stdout</CODE>
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 
<A HREF="http://space.mit.edu/cxc/software/slang/modules/pvm/examples/master">master</A> process simply prints out this information.</P>

<H3>The <CODE>slave</CODE> program</H3>


<P>The 
<A HREF="http://space.mit.edu/cxc/software/slang/modules/pvm/examples/master">slave</A> process in this example is relatively simple.
Its command line arguments provide the task to be completed.
These arguments are then passed to <CODE>pvm_ms_run_slave</CODE>
<BLOCKQUOTE><CODE>
<PRE>
  pvm_ms_run_slave (__argv[[1:]]);
</PRE>
</CODE></BLOCKQUOTE>

which spawns a subshell, runs the specified command,
communicates the task completion status to the parent process
and exits.</P>

<HR>
<A HREF="pvm-4.html">Next</A>
<A HREF="pvm-2.html">Previous</A>
<A HREF="pvm.html#toc3">Contents</A>
</BODY>
</HTML>