process_group.rst 18 KB

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