• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1.. Copyright (C) 2004-2008 The Trustees of Indiana University.
2   Use, modification and distribution is subject to the Boost Software
3   License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
4   http://www.boost.org/LICENSE_1_0.txt)
5
6==================================
7|Logo| Parallel BGL Process Groups
8==================================
9
10.. contents::
11
12Introduction
13------------
14
15Process groups are an abstraction of a set of communicating processes
16that coordinate to solve the same problem. Process groups contain
17facilities for identifying the processes within that group, sending
18and receiving messages between the processes in that group, and
19performing collective communications involving all processes in the
20group simultaneously.
21
22Communication model
23-------------------
24
25Process groups are based on an extended version of the Bulk
26Synchronous Parallel (BSP) model of computation. Parallel computations
27in the BSP model are organized into *supersteps*, each of which
28consists of a computation phase followed by a communication
29phase. During the computation phase, all processes in the process
30group work exclusively on local data, and there is no inter-process
31communication. During the communication phase, all of the processes
32exchange message with each other. Messages sent in the communication
33phase of a superstep will be received in the next superstep.
34
35The boundary between supersteps in the Parallel BGL corresponds to the
36``synchronize`` operation. Whenever a process has completed its local
37computation phase and sent all of the messages required for that
38superstep, it invokes the ``synchronize`` operation on the process
39group. Once all processes in the process group have entered
40``synchronize``, they exchange messages and then continue with the
41next superstep.
42
43The Parallel BGL loosens the BSP model significantly, to provide a
44more natural programming model that also provides some performance
45benefits over the strict BSP model. The primary extension is the
46ability to receive messages sent within the same superstep
47"asynchronously", either to free up message buffers or to respond to
48an immediate request for information. For particularly unstructured
49computations, the ability to send a message and get an immediate reply
50can simplify many computations that would otherwise need to be split
51into two separate supersteps. Additionally, the Parallel BGL augments
52the BSP model with support for multiple distributed data structures,
53each of which are provided with a different communication space but
54whose messages will all be synchronized concurrently.
55
56Distributed data structures
57~~~~~~~~~~~~~~~~~~~~~~~~~~~
58
59A typical computation with the Parallel BGL involves several
60distributed data structures working in concern. For example, a simple
61breadth-first search involves the distributed graph data structure
62containing the graph itself, a distributed queue that manages the
63traversal through the graph, and a distributed property map that
64tracks which vertices have already been visited as part of the
65search.
66
67The Parallel BGL manages these distributed data structures by allowing
68each of the data structures to attach themselves to the process group
69itself. When a distributed data structure attaches to the process
70group, it receives its own copy of the process group that allows the
71distributed data structure to communicate without colliding with the
72communications from other distributed data structures. When the
73process group is synchronized, all of the distributed data structures
74attached to that process group are automatically synchronized, so that
75all of the distributed data structures in a computation remain
76synchronized.
77
78A distributed data structure attaches itself to the process group by
79creating a copy of the process group and passing an
80``attach_distributed_object`` flag to the process group
81constructor. So long as this copy of the process group persists, the
82distributed data structure is attached the process group. For this
83reason, most distributed data structures keep a copy of the process
84group as member data, constructing the member with
85``attach_distributed_object``, e.g.,
86
87::
88
89  template<typename ProcessGroup>
90  struct distributed_data_structure
91  {
92    explicit distributed_data_structure(const ProcessGroup& pg)
93      : process_group(pg, boost::parallel::attach_distributed_object())
94    { }
95
96  private:
97    ProcessGroup process_group;
98  };
99
100
101Asynchronous receives
102~~~~~~~~~~~~~~~~~~~~~
103
104Distributed data structures in the Parallel BGL can "asynchronously"
105receive and process messages before the end of a BSP
106superstep. Messages can be received any time that a process is inside
107the process group operations, and the scheduling of message receives
108is entirely managed by the process group.
109
110Distributed data structures receive messages through
111"triggers". Triggers are function objects responsible for processing a
112received message. Each trigger is registered with the ``trigger``
113method of the process group using a specific message
114tag (an integer) and the type of data that is expected to be
115contained within that message. Whenever a message with that tag
116becomes available, the progress group will call the trigger with the
117source of the message, the message tag, the data contained in the
118message, and the "context" of the message.
119
120The majority of triggers have no return value, although it is common
121that the triggers send messages back to the source process. In certain
122cases where the trigger's purpose is to immediately reply with a
123value, the trigger should be registered with the
124``trigger_with_reply`` method and should return the value that will be
125sent back to the caller. The ``trigger_with_reply`` facility is only
126useful in conjunction with out-of-band messaging, discussed next.
127
128Out-of-band messaging
129~~~~~~~~~~~~~~~~~~~~~
130
131The majority of messages sent by the Parallel BGL are sent through the
132normal send operations, to be received in the next superstep or, in
133some cases, received "early" by a trigger. These messages are not
134time-sensitive, so they will be delivered whenever the process group
135processes them.
136
137Some messages, however, require immediate responses. For example, if a
138process needs to determine the current value associated with a vertex
139owned by another process, the first process must send a request to the
140second process and block while waiting for a response. For such
141messages, the Parallel BGL's process groups provide an out-of-band
142messaging mechanism. Out-of-band messages are transmitted immediately,
143with a much higher priority than other messages. The sending of
144out-of-band messages can be coupled with a receive operation that
145waits until the remote process has received the message and sent its
146reply. For example, in the following code the process sends a message
147containing the string ``name`` to process ``owner`` with tag
148``msg_get_descriptor_by_name`` via an out-of-band message. The
149receiver of that message will immediately deliver the message via a
150trigger, that returns the resulting value--a
151``vertex_descriptor``--that will be passed back to the process that
152initiated the communication. The full communication happens
153immediately, within the current superstep.
154
155::
156
157  std::string name;
158  vertex_descriptor descriptor;
159  send_oob_with_reply(process_group, owner, msg_get_descriptor_by_name,
160                      name, descriptor);
161
162Reference
163---------
164
165The Parallel BGL process groups specify an interface that can be
166implemented by various communication subsystems. In this reference
167section, we use the placeholder type ``ProcessGroup`` to stand in for
168the various process group implementations that exist. There is only
169one implementation of the process group interface at this time:
170
171  - `MPI BSP process group`_
172
173::
174
175  enum trigger_receive_context {
176    trc_none,
177    trc_in_synchronization,
178    trc_early_receive,
179    trc_out_of_band
180  };
181
182  class ProcessGroup
183  {
184    // Process group constructors
185    ProcessGroup();
186    ProcessGroup(const ProcessGroup&, boost::parallel::attach_distributed_object);
187
188    // Triggers
189    template<typename Type, typename Handler>
190      void trigger(int tag, const Handler& handler);
191
192    template<typename Type, typename Handler>
193      void trigger_with_reply(int tag, const Handler& handler);
194
195    trigger_receive_context trigger_context() const;
196
197    // Helper operations
198    void poll();
199    ProcessGroup base() const;
200  };
201
202  // Process query
203  int process_id(const ProcessGroup&);
204  int num_processes(const ProcessGroup&);
205
206  // Message transmission
207  template<typename T>
208    void send(const ProcessGroup& pg, int dest, int tag, const T& value);
209
210  template<typename T>
211    void receive(const ProcessGroup& pg, int source, int tag, T& value);
212
213  optional<std::pair<int, int> > probe(const ProcessGroup& pg);
214
215  // Synchronization
216  void synchronize(const ProcessGroup& pg);
217
218  // Out-of-band communication
219  template<typename T>
220    void send_oob(const ProcessGroup& pg, int dest, int tag, const T& value);
221
222  template<typename T, typename U>
223    void
224    send_oob_with_reply(const ProcessGroup& pg, int dest, int
225                        tag, const T& send_value, U& receive_value);
226
227  template<typename T>
228    void receive_oob(const ProcessGroup& pg, int source, int tag, T& value);
229
230
231Process group constructors
232~~~~~~~~~~~~~~~~~~~~~~~~~~
233
234::
235
236    ProcessGroup();
237
238Constructs a new process group with a different communication space
239from any other process group.
240
241-----------------------------------------------------------------------------
242
243::
244
245    ProcessGroup(const ProcessGroup& pg, boost::parallel::attach_distributed_object);
246
247Attaches a new distributed data structure to the process group
248``pg``. The resulting process group can be used for communication
249within that new distributed data structure. When the newly-constructed
250process group is eventually destroyed, the distributed data structure
251is detached from the process group.
252
253Triggers
254~~~~~~~~
255
256::
257
258    template<typename Type, typename Handler>
259      void trigger(int tag, const Handler& handler);
260
261Registers a trigger with the given process group. The trigger will
262watch for messages with the given ``tag``. When such a message is
263available, it will be received into a value of type ``Type``, and the
264function object ``handler`` will be invoked with four parameters:
265
266source
267  The rank of the source process (an ``int``)
268
269tag
270  The tag used to send the message (also an ``int``)
271
272data:
273  The data transmitted with the message. The data will have the type
274  specified when the trigger was registered.
275
276context:
277  The context in which the trigger is executed. This will be a value of
278  type ``trigger_receive_context``, which stages whether the trigger
279  is being executed during synchronization, asynchronously in response
280  to an "early" receive (often to free up communication buffers), or
281  in response to an "out-of-band" message.
282
283Triggers can only be registered by process groups that result from
284attaching a distributed data structure. A trigger can be invoked in
285response to either a normal send operation or an out-of-band send
286operation. There is also a `simple trigger interface`_ for defining
287triggers in common cases.
288
289-----------------------------------------------------------------------------
290
291::
292
293    template<typename Type, typename Handler>
294      void trigger_with_reply(int tag, const Handler& handler);
295
296Like the ``trigger`` method, registers a trigger with the given
297process group. The trigger will watch for messages with the given
298``tag``. When such a message is available, it will be received into a
299value of type ``Type`` and ``handler`` will be invoked, just as with a
300normal trigger. However, a trigger registered with
301``trigger_with_reply`` must return a value, which will be immediately
302sent back to the process that initiated the send resulting in this
303trigger. Thus, ``trigger_with_reply`` should only be used for messages
304that need immediate responses. These triggers can only be invoked via
305the out-of-band sends that wait for the reply, via
306``send_oob_with_reply``. There is also a `simple trigger interface`_
307for defining triggers in common cases.
308
309-----------------------------------------------------------------------------
310
311::
312
313    trigger_receive_context trigger_context() const;
314
315Retrieves the current context of the process group with respect to the
316invocation of triggers. When ``trc_none``, the process group is not
317currently invoking any triggers. Otherwise, this value describes in
318what context the currently executing trigger is being invoked.
319
320
321Helper operations
322~~~~~~~~~~~~~~~~~
323
324::
325
326  void poll();
327
328Permits the process group to receive any incomining messages,
329processing them via triggers. If you have a long-running computation
330that does not invoke any of the process group's communication
331routines, you should call ``poll`` occasionally to along incoming
332messages to be processed.
333
334-----------------------------------------------------------------------------
335
336::
337
338    ProcessGroup base() const;
339
340Retrieves the "base" process group for this process group, which is a
341copy of the underlying process group that does not reference any
342specific distributed data structure.
343
344Process query
345~~~~~~~~~~~~~
346
347::
348
349  int process_id(const ProcessGroup& pg);
350
351Retrieves the ID (or "rank") of the calling process within the process
352group. Process IDs are values in the range [0, ``num_processes(pg)``)
353that uniquely identify the process. Process IDs can be used to
354initiate communication with another process.
355
356-----------------------------------------------------------------------------
357
358::
359
360  int num_processes(const ProcessGroup& pg);
361
362Returns the number of processes within the process group.
363
364
365Message transmission
366~~~~~~~~~~~~~~~~~~~~
367
368::
369
370  template<typename T>
371    void send(const ProcessGroup& pg, int dest, int tag, const T& value);
372
373Sends a message with the given ``tag`` and carrying the given
374``value`` to the process with ID ``dest`` in the given process
375group. All message sends are non-blocking, meaning that this send
376operation will not block while waiting for the communication to
377complete. There is no guarantee when the message will be received,
378except that it will become available to the destination process by the
379end of the superstep, in the collective call to ``synchronize``.
380
381Any type of value can be transmitted via ``send``, so long as it
382provides the appropriate functionality to be serialized with the
383Boost.Serialization library.
384
385-----------------------------------------------------------------------------
386
387::
388
389  template<typename T>
390    void receive(const ProcessGroup& pg, int source, int tag, T& value);
391
392Receives a message with the given ``tag`` sent from the process
393``source``, updating ``value`` with the payload of the message. This
394receive operation can only receive messages sent within the previous
395superstep via the ``send`` operation. If no such message is available
396at the time ``receive`` is called, the program is ill-formed.
397
398-----------------------------------------------------------------------------
399
400::
401
402  optional<std::pair<int, int> > probe(const ProcessGroup& pg);
403
404Determines whether a message is available. The probe operation checks
405for any messages that were sent in the previous superstep but have not
406yet been received. If such a message exists, ``probe`` returns a
407(source, tag) pair describing the message. Otherwise, ``probe`` will
408return an empty ``boost::optional``.
409
410A typical use of ``probe`` is to continually probe for messages at the
411beginning of the superstep, receiving and processing those messages
412until no messages remain.
413
414
415Synchronization
416~~~~~~~~~~~~~~~
417
418::
419
420  void synchronize(const ProcessGroup& pg);
421
422The ``synchronize`` function is a collective operation that must be
423invoked by all of the processes within the process group. A call to
424``synchronize`` marks the end of a superstep in the parallel
425computation. All messages sent before the end of the superstep will be
426received into message buffers, and can be processed by the program in
427the next superstep. None of the processes will leave the
428``synchronize`` function until all of the processes have entered the
429function and exchanged messages, so that all processes are always on
430the same superstep.
431
432Out-of-band communication
433~~~~~~~~~~~~~~~~~~~~~~~~~
434
435::
436
437  template<typename T>
438    void send_oob(const ProcessGroup& pg, int dest, int tag, const T& value);
439
440Sends and out-of-band message. This out-of-band send operation acts
441like the normal ``send`` operation, except that out-of-band messages
442are delivered immediately through a high-priority channel.
443
444-----------------------------------------------------------------------------
445
446::
447
448  template<typename T, typename U>
449    void
450    send_oob_with_reply(const ProcessGroup& pg, int dest, int
451                        tag, const T& send_value, U& receive_value);
452
453Sends an out-of-band message and waits for a reply. The
454``send_oob_with_reply`` function can only be invoked with message tags
455that correspond to triggers registered with
456``trigger_with_reply``. This operation will send the message
457immediately (through the high-priority, out-of-band channel), then
458wait until the remote process sends a reply. The data from the reply
459is stored into ``receive_value``.
460
461-----------------------------------------------------------------------------
462
463::
464
465  template<typename T>
466    void receive_oob(const ProcessGroup& pg, int source, int tag, T& value);
467
468Receives an out-of-band message with the given ``source`` and
469``tag``. As with the normal ``receive`` operation, it is an error to
470call ``receive_oob`` if no message matching the source and tag is
471available. This routine is used only rarely; for most circumstances,
472use ``send_oob_with_reply`` to perform an immediate send with a
473reply.
474
475-----------------------------------------------------------------------------
476
477Copyright (C) 2007 Douglas Gregor
478
479Copyright (C) 2007 Matthias Troyer
480
481.. |Logo| image:: pbgl-logo.png
482            :align: middle
483            :alt: Parallel BGL
484            :target: http://www.osl.iu.edu/research/pbgl
485
486.. _MPI BSP process group: mpi_bsp_process_group.html
487.. _Simple trigger interface: simple_trigger.html
488