communicator.hpp 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792
  1. // Copyright (C) 2005, 2006 Douglas Gregor <doug.gregor -at- gmail.com>.
  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. /** @file communicator.hpp
  6. *
  7. * This header defines the @c communicator class, which is the basis
  8. * of all communication within Boost.MPI, and provides point-to-point
  9. * communication operations.
  10. */
  11. #ifndef BOOST_MPI_COMMUNICATOR_HPP
  12. #define BOOST_MPI_COMMUNICATOR_HPP
  13. #include <boost/assert.hpp>
  14. #include <boost/mpi/config.hpp>
  15. #include <boost/mpi/exception.hpp>
  16. #include <boost/optional.hpp>
  17. #include <boost/shared_ptr.hpp>
  18. #include <boost/mpi/datatype.hpp>
  19. #include <boost/mpi/nonblocking.hpp>
  20. #include <utility>
  21. #include <iterator>
  22. #include <stdexcept> // for std::range_error
  23. // For (de-)serializing sends and receives
  24. #include <boost/mpi/packed_oarchive.hpp>
  25. #include <boost/mpi/packed_iarchive.hpp>
  26. // For (de-)serializing skeletons and content
  27. #include <boost/mpi/skeleton_and_content_fwd.hpp>
  28. // For (de-)serializing arrays
  29. #include <boost/serialization/array.hpp>
  30. #include <boost/mpi/detail/point_to_point.hpp>
  31. #include <boost/mpi/status.hpp>
  32. #include <boost/mpi/request.hpp>
  33. #ifdef BOOST_MSVC
  34. # pragma warning(push)
  35. # pragma warning(disable : 4800) // forcing to bool 'true' or 'false'
  36. #endif
  37. namespace boost { namespace mpi {
  38. /**
  39. * @brief A constant representing "any process."
  40. *
  41. * This constant may be used for the @c source parameter of @c receive
  42. * operations to indicate that a message may be received from any
  43. * source.
  44. */
  45. const int any_source = MPI_ANY_SOURCE;
  46. /**
  47. * @brief A constant representing "any tag."
  48. *
  49. * This constant may be used for the @c tag parameter of @c receive
  50. * operations to indicate that a @c send with any tag will be matched
  51. * by the receive.
  52. */
  53. const int any_tag = MPI_ANY_TAG;
  54. /**
  55. * @brief Enumeration used to describe how to adopt a C @c MPI_Comm into
  56. * a Boost.MPI communicator.
  57. *
  58. * The values for this enumeration determine how a Boost.MPI
  59. * communicator will behave when constructed with an MPI
  60. * communicator. The options are:
  61. *
  62. * - @c comm_duplicate: Duplicate the MPI_Comm communicator to
  63. * create a new communicator (e.g., with MPI_Comm_dup). This new
  64. * MPI_Comm communicator will be automatically freed when the
  65. * Boost.MPI communicator (and all copies of it) is destroyed.
  66. *
  67. * - @c comm_take_ownership: Take ownership of the communicator. It
  68. * will be freed automatically when all of the Boost.MPI
  69. * communicators go out of scope. This option must not be used with
  70. * MPI_COMM_WORLD.
  71. *
  72. * - @c comm_attach: The Boost.MPI communicator will reference the
  73. * existing MPI communicator but will not free it when the Boost.MPI
  74. * communicator goes out of scope. This option should only be used
  75. * when the communicator is managed by the user or MPI library
  76. * (e.g., MPI_COMM_WORLD).
  77. */
  78. enum comm_create_kind { comm_duplicate, comm_take_ownership, comm_attach };
  79. /**
  80. * INTERNAL ONLY
  81. *
  82. * Forward declaration of @c group needed for the @c group
  83. * constructor and accessor.
  84. */
  85. class group;
  86. /**
  87. * INTERNAL ONLY
  88. *
  89. * Forward declaration of @c intercommunicator needed for the "cast"
  90. * from a communicator to an intercommunicator.
  91. */
  92. class intercommunicator;
  93. /**
  94. * INTERNAL ONLY
  95. *
  96. * Forward declaration of @c graph_communicator needed for the "cast"
  97. * from a communicator to a graph communicator.
  98. */
  99. class graph_communicator;
  100. /**
  101. * @brief A communicator that permits communication and
  102. * synchronization among a set of processes.
  103. *
  104. * The @c communicator class abstracts a set of communicating
  105. * processes in MPI. All of the processes that belong to a certain
  106. * communicator can determine the size of the communicator, their rank
  107. * within the communicator, and communicate with any other processes
  108. * in the communicator.
  109. */
  110. class BOOST_MPI_DECL communicator
  111. {
  112. public:
  113. /**
  114. * Build a new Boost.MPI communicator for @c MPI_COMM_WORLD.
  115. *
  116. * Constructs a Boost.MPI communicator that attaches to @c
  117. * MPI_COMM_WORLD. This is the equivalent of constructing with
  118. * @c (MPI_COMM_WORLD, comm_attach).
  119. */
  120. communicator();
  121. /**
  122. * Build a new Boost.MPI communicator based on the MPI communicator
  123. * @p comm.
  124. *
  125. * @p comm may be any valid MPI communicator. If @p comm is
  126. * MPI_COMM_NULL, an empty communicator (that cannot be used for
  127. * communication) is created and the @p kind parameter is
  128. * ignored. Otherwise, the @p kind parameters determines how the
  129. * Boost.MPI communicator will be related to @p comm:
  130. *
  131. * - If @p kind is @c comm_duplicate, duplicate @c comm to create
  132. * a new communicator. This new communicator will be freed when
  133. * the Boost.MPI communicator (and all copies of it) is destroyed.
  134. * This option is only permitted if @p comm is a valid MPI
  135. * intracommunicator or if the underlying MPI implementation
  136. * supports MPI 2.0 (which supports duplication of
  137. * intercommunicators).
  138. *
  139. * - If @p kind is @c comm_take_ownership, take ownership of @c
  140. * comm. It will be freed automatically when all of the Boost.MPI
  141. * communicators go out of scope. This option must not be used
  142. * when @c comm is MPI_COMM_WORLD.
  143. *
  144. * - If @p kind is @c comm_attach, this Boost.MPI communicator
  145. * will reference the existing MPI communicator @p comm but will
  146. * not free @p comm when the Boost.MPI communicator goes out of
  147. * scope. This option should only be used when the communicator is
  148. * managed by the user or MPI library (e.g., MPI_COMM_WORLD).
  149. */
  150. communicator(const MPI_Comm& comm, comm_create_kind kind);
  151. /**
  152. * Build a new Boost.MPI communicator based on a subgroup of another
  153. * MPI communicator.
  154. *
  155. * This routine will construct a new communicator containing all of
  156. * the processes from communicator @c comm that are listed within
  157. * the group @c subgroup. Equivalent to @c MPI_Comm_create.
  158. *
  159. * @param comm An MPI communicator.
  160. *
  161. * @param subgroup A subgroup of the MPI communicator, @p comm, for
  162. * which we will construct a new communicator.
  163. */
  164. communicator(const communicator& comm, const boost::mpi::group& subgroup);
  165. /**
  166. * @brief Determine the rank of the executing process in a
  167. * communicator.
  168. *
  169. * This routine is equivalent to @c MPI_Comm_rank.
  170. *
  171. * @returns The rank of the process in the communicator, which
  172. * will be a value in [0, size())
  173. */
  174. int rank() const;
  175. /**
  176. * @brief Determine the number of processes in a communicator.
  177. *
  178. * This routine is equivalent to @c MPI_Comm_size.
  179. *
  180. * @returns The number of processes in the communicator.
  181. */
  182. int size() const;
  183. /**
  184. * This routine constructs a new group whose members are the
  185. * processes within this communicator. Equivalent to
  186. * calling @c MPI_Comm_group.
  187. */
  188. boost::mpi::group group() const;
  189. // ----------------------------------------------------------------
  190. // Point-to-point communication
  191. // ----------------------------------------------------------------
  192. /**
  193. * @brief Send data to another process.
  194. *
  195. * This routine executes a potentially blocking send with tag @p tag
  196. * to the process with rank @p dest. It can be received by the
  197. * destination process with a matching @c recv call.
  198. *
  199. * The given @p value must be suitable for transmission over
  200. * MPI. There are several classes of types that meet these
  201. * requirements:
  202. *
  203. * - Types with mappings to MPI data types: If @c
  204. * is_mpi_datatype<T> is convertible to @c mpl::true_, then @p
  205. * value will be transmitted using the MPI data type
  206. * @c get_mpi_datatype<T>(). All primitive C++ data types that have
  207. * MPI equivalents, e.g., @c int, @c float, @c char, @c double,
  208. * etc., have built-in mappings to MPI data types. You may turn a
  209. * Serializable type with fixed structure into an MPI data type by
  210. * specializing @c is_mpi_datatype for your type.
  211. *
  212. * - Serializable types: Any type that provides the @c serialize()
  213. * functionality required by the Boost.Serialization library can be
  214. * transmitted and received.
  215. *
  216. * - Packed archives and skeletons: Data that has been packed into
  217. * an @c mpi::packed_oarchive or the skeletons of data that have
  218. * been backed into an @c mpi::packed_skeleton_oarchive can be
  219. * transmitted, but will be received as @c mpi::packed_iarchive and
  220. * @c mpi::packed_skeleton_iarchive, respectively, to allow the
  221. * values (or skeletons) to be extracted by the destination process.
  222. *
  223. * - Content: Content associated with a previously-transmitted
  224. * skeleton can be transmitted by @c send and received by @c
  225. * recv. The receiving process may only receive content into the
  226. * content of a value that has been constructed with the matching
  227. * skeleton.
  228. *
  229. * For types that have mappings to an MPI data type (including the
  230. * concent of a type), an invocation of this routine will result in
  231. * a single MPI_Send call. For variable-length data, e.g.,
  232. * serialized types and packed archives, two messages will be sent
  233. * via MPI_Send: one containing the length of the data and the
  234. * second containing the data itself. Note that the transmission
  235. * mode for variable-length data is an implementation detail that
  236. * is subject to change.
  237. *
  238. * @param dest The rank of the remote process to which the data
  239. * will be sent.
  240. *
  241. * @param tag The tag that will be associated with this message. Tags
  242. * may be any integer between zero and an implementation-defined
  243. * upper limit. This limit is accessible via @c environment::max_tag().
  244. *
  245. * @param value The value that will be transmitted to the
  246. * receiver. The type @c T of this value must meet the aforementioned
  247. * criteria for transmission.
  248. */
  249. template<typename T>
  250. void send(int dest, int tag, const T& value) const;
  251. /**
  252. * @brief Send the skeleton of an object.
  253. *
  254. * This routine executes a potentially blocking send with tag @p
  255. * tag to the process with rank @p dest. It can be received by the
  256. * destination process with a matching @c recv call. This variation
  257. * on @c send will be used when a send of a skeleton is explicitly
  258. * requested via code such as:
  259. *
  260. * @code
  261. * comm.send(dest, tag, skeleton(object));
  262. * @endcode
  263. *
  264. * The semantics of this routine are equivalent to that of sending
  265. * a @c packed_skeleton_oarchive storing the skeleton of the @c
  266. * object.
  267. *
  268. * @param dest The rank of the remote process to which the skeleton
  269. * will be sent.
  270. *
  271. * @param tag The tag that will be associated with this message. Tags
  272. * may be any integer between zero and an implementation-defined
  273. * upper limit. This limit is accessible via @c environment::max_tag().
  274. *
  275. * @param proxy The @c skeleton_proxy containing a reference to the
  276. * object whose skeleton will be transmitted.
  277. *
  278. */
  279. template<typename T>
  280. void send(int dest, int tag, const skeleton_proxy<T>& proxy) const;
  281. /**
  282. * @brief Send an array of values to another process.
  283. *
  284. * This routine executes a potentially blocking send of an array of
  285. * data with tag @p tag to the process with rank @p dest. It can be
  286. * received by the destination process with a matching array @c
  287. * recv call.
  288. *
  289. * If @c T is an MPI datatype, an invocation of this routine will
  290. * be mapped to a single call to MPI_Send, using the datatype @c
  291. * get_mpi_datatype<T>().
  292. *
  293. * @param dest The process rank of the remote process to which
  294. * the data will be sent.
  295. *
  296. * @param tag The tag that will be associated with this message. Tags
  297. * may be any integer between zero and an implementation-defined
  298. * upper limit. This limit is accessible via @c environment::max_tag().
  299. *
  300. * @param values The array of values that will be transmitted to the
  301. * receiver. The type @c T of these values must be mapped to an MPI
  302. * data type.
  303. *
  304. * @param n The number of values stored in the array. The destination
  305. * process must call receive with at least this many elements to
  306. * correctly receive the message.
  307. */
  308. template<typename T>
  309. void send(int dest, int tag, const T* values, int n) const;
  310. /**
  311. * @brief Send a message to another process without any data.
  312. *
  313. * This routine executes a potentially blocking send of a message
  314. * to another process. The message contains no extra data, and can
  315. * therefore only be received by a matching call to @c recv().
  316. *
  317. * @param dest The process rank of the remote process to which
  318. * the message will be sent.
  319. *
  320. * @param tag The tag that will be associated with this message. Tags
  321. * may be any integer between zero and an implementation-defined
  322. * upper limit. This limit is accessible via @c environment::max_tag().
  323. *
  324. */
  325. void send(int dest, int tag) const;
  326. /**
  327. * @brief Receive data from a remote process.
  328. *
  329. * This routine blocks until it receives a message from the process @p
  330. * source with the given @p tag. The type @c T of the @p value must be
  331. * suitable for transmission over MPI, which includes serializable
  332. * types, types that can be mapped to MPI data types (including most
  333. * built-in C++ types), packed MPI archives, skeletons, and content
  334. * associated with skeletons; see the documentation of @c send for a
  335. * complete description.
  336. *
  337. * @param source The process that will be sending data. This will
  338. * either be a process rank within the communicator or the
  339. * constant @c any_source, indicating that we can receive the
  340. * message from any process.
  341. *
  342. * @param tag The tag that matches a particular kind of message sent
  343. * by the source process. This may be any tag value permitted by @c
  344. * send. Alternatively, the argument may be the constant @c any_tag,
  345. * indicating that this receive matches a message with any tag.
  346. *
  347. * @param value Will contain the value of the message after a
  348. * successful receive. The type of this value must match the value
  349. * transmitted by the sender, unless the sender transmitted a packed
  350. * archive or skeleton: in these cases, the sender transmits a @c
  351. * packed_oarchive or @c packed_skeleton_oarchive and the
  352. * destination receives a @c packed_iarchive or @c
  353. * packed_skeleton_iarchive, respectively.
  354. *
  355. * @returns Information about the received message.
  356. */
  357. template<typename T>
  358. status recv(int source, int tag, T& value) const;
  359. /**
  360. * @brief Receive a skeleton from a remote process.
  361. *
  362. * This routine blocks until it receives a message from the process @p
  363. * source with the given @p tag containing a skeleton.
  364. *
  365. * @param source The process that will be sending data. This will
  366. * either be a process rank within the communicator or the constant
  367. * @c any_source, indicating that we can receive the message from
  368. * any process.
  369. *
  370. * @param tag The tag that matches a particular kind of message
  371. * sent by the source process. This may be any tag value permitted
  372. * by @c send. Alternatively, the argument may be the constant @c
  373. * any_tag, indicating that this receive matches a message with any
  374. * tag.
  375. *
  376. * @param proxy The @c skeleton_proxy containing a reference to the
  377. * object that will be reshaped to match the received skeleton.
  378. *
  379. * @returns Information about the received message.
  380. */
  381. template<typename T>
  382. status recv(int source, int tag, const skeleton_proxy<T>& proxy) const;
  383. /**
  384. * @brief Receive a skeleton from a remote process.
  385. *
  386. * This routine blocks until it receives a message from the process @p
  387. * source with the given @p tag containing a skeleton.
  388. *
  389. * @param source The process that will be sending data. This will
  390. * either be a process rank within the communicator or the constant
  391. * @c any_source, indicating that we can receive the message from
  392. * any process.
  393. *
  394. * @param tag The tag that matches a particular kind of message
  395. * sent by the source process. This may be any tag value permitted
  396. * by @c send. Alternatively, the argument may be the constant @c
  397. * any_tag, indicating that this receive matches a message with any
  398. * tag.
  399. *
  400. * @param proxy The @c skeleton_proxy containing a reference to the
  401. * object that will be reshaped to match the received skeleton.
  402. *
  403. * @returns Information about the received message.
  404. */
  405. template<typename T>
  406. status recv(int source, int tag, skeleton_proxy<T>& proxy) const;
  407. /**
  408. * @brief Receive an array of values from a remote process.
  409. *
  410. * This routine blocks until it receives an array of values from the
  411. * process @p source with the given @p tag. If the type @c T is
  412. *
  413. * @param source The process that will be sending data. This will
  414. * either be a process rank within the communicator or the
  415. * constant @c any_source, indicating that we can receive the
  416. * message from any process.
  417. *
  418. * @param tag The tag that matches a particular kind of message sent
  419. * by the source process. This may be any tag value permitted by @c
  420. * send. Alternatively, the argument may be the constant @c any_tag,
  421. * indicating that this receive matches a message with any tag.
  422. *
  423. * @param values Will contain the values in the message after a
  424. * successful receive. The type of these elements must match the
  425. * type of the elements transmitted by the sender.
  426. *
  427. * @param n The number of values that can be stored into the @p
  428. * values array. This shall not be smaller than the number of
  429. * elements transmitted by the sender.
  430. *
  431. * @throws std::range_error if the message to be received contains
  432. * more than @p n values.
  433. *
  434. * @returns Information about the received message.
  435. */
  436. template<typename T>
  437. status recv(int source, int tag, T* values, int n) const;
  438. /**
  439. * @brief Receive a message from a remote process without any data.
  440. *
  441. * This routine blocks until it receives a message from the process
  442. * @p source with the given @p tag.
  443. *
  444. * @param source The process that will be sending the message. This
  445. * will either be a process rank within the communicator or the
  446. * constant @c any_source, indicating that we can receive the
  447. * message from any process.
  448. *
  449. * @param tag The tag that matches a particular kind of message
  450. * sent by the source process. This may be any tag value permitted
  451. * by @c send. Alternatively, the argument may be the constant @c
  452. * any_tag, indicating that this receive matches a message with any
  453. * tag.
  454. *
  455. * @returns Information about the received message.
  456. */
  457. status recv(int source, int tag) const;
  458. /** @brief Send a message to remote process nd receive another message
  459. * from another process.
  460. */
  461. template<typename T>
  462. status sendrecv(int dest, int stag, const T& sval, int src, int rtag, T& rval) const;
  463. /**
  464. * @brief Send a message to a remote process without blocking.
  465. *
  466. * The @c isend method is functionality identical to the @c send
  467. * method and transmits data in the same way, except that @c isend
  468. * will not block while waiting for the data to be
  469. * transmitted. Instead, a request object will be immediately
  470. * returned, allowing one to query the status of the communication
  471. * or wait until it has completed.
  472. *
  473. * @param dest The rank of the remote process to which the data
  474. * will be sent.
  475. *
  476. * @param tag The tag that will be associated with this message. Tags
  477. * may be any integer between zero and an implementation-defined
  478. * upper limit. This limit is accessible via @c environment::max_tag().
  479. *
  480. * @param value The value that will be transmitted to the
  481. * receiver. The type @c T of this value must meet the aforementioned
  482. * criteria for transmission.
  483. *
  484. * @returns a @c request object that describes this communication.
  485. */
  486. template<typename T>
  487. request isend(int dest, int tag, const T& value) const;
  488. /**
  489. * @brief Send the skeleton of an object without blocking.
  490. *
  491. * This routine is functionally identical to the @c send method for
  492. * @c skeleton_proxy objects except that @c isend will not block
  493. * while waiting for the data to be transmitted. Instead, a request
  494. * object will be immediately returned, allowing one to query the
  495. * status of the communication or wait until it has completed.
  496. *
  497. * The semantics of this routine are equivalent to a non-blocking
  498. * send of a @c packed_skeleton_oarchive storing the skeleton of
  499. * the @c object.
  500. *
  501. * @param dest The rank of the remote process to which the skeleton
  502. * will be sent.
  503. *
  504. * @param tag The tag that will be associated with this message. Tags
  505. * may be any integer between zero and an implementation-defined
  506. * upper limit. This limit is accessible via @c environment::max_tag().
  507. *
  508. * @param proxy The @c skeleton_proxy containing a reference to the
  509. * object whose skeleton will be transmitted.
  510. *
  511. * @returns a @c request object that describes this communication.
  512. */
  513. template<typename T>
  514. request isend(int dest, int tag, const skeleton_proxy<T>& proxy) const;
  515. /**
  516. * @brief Send an array of values to another process without
  517. * blocking.
  518. *
  519. * This routine is functionally identical to the @c send method for
  520. * arrays except that @c isend will not block while waiting for the
  521. * data to be transmitted. Instead, a request object will be
  522. * immediately returned, allowing one to query the status of the
  523. * communication or wait until it has completed.
  524. *
  525. * @param dest The process rank of the remote process to which
  526. * the data will be sent.
  527. *
  528. * @param tag The tag that will be associated with this message. Tags
  529. * may be any integer between zero and an implementation-defined
  530. * upper limit. This limit is accessible via @c environment::max_tag().
  531. *
  532. * @param values The array of values that will be transmitted to the
  533. * receiver. The type @c T of these values must be mapped to an MPI
  534. * data type.
  535. *
  536. * @param n The number of values stored in the array. The destination
  537. * process must call receive with at least this many elements to
  538. * correctly receive the message.
  539. *
  540. * @returns a @c request object that describes this communication.
  541. */
  542. template<typename T>
  543. request isend(int dest, int tag, const T* values, int n) const;
  544. /**
  545. * @brief Send a message to another process without any data
  546. * without blocking.
  547. *
  548. * This routine is functionally identical to the @c send method for
  549. * sends with no data, except that @c isend will not block while
  550. * waiting for the message to be transmitted. Instead, a request
  551. * object will be immediately returned, allowing one to query the
  552. * status of the communication or wait until it has completed.
  553. *
  554. * @param dest The process rank of the remote process to which
  555. * the message will be sent.
  556. *
  557. * @param tag The tag that will be associated with this message. Tags
  558. * may be any integer between zero and an implementation-defined
  559. * upper limit. This limit is accessible via @c environment::max_tag().
  560. *
  561. *
  562. * @returns a @c request object that describes this communication.
  563. */
  564. request isend(int dest, int tag) const;
  565. /**
  566. * @brief Prepare to receive a message from a remote process.
  567. *
  568. * The @c irecv method is functionally identical to the @c recv
  569. * method and receive data in the same way, except that @c irecv
  570. * will not block while waiting for data to be
  571. * transmitted. Instead, it immediately returns a request object
  572. * that allows one to query the status of the receive or wait until
  573. * it has completed.
  574. *
  575. * @param source The process that will be sending data. This will
  576. * either be a process rank within the communicator or the
  577. * constant @c any_source, indicating that we can receive the
  578. * message from any process.
  579. *
  580. * @param tag The tag that matches a particular kind of message sent
  581. * by the source process. This may be any tag value permitted by @c
  582. * send. Alternatively, the argument may be the constant @c any_tag,
  583. * indicating that this receive matches a message with any tag.
  584. *
  585. * @param value Will contain the value of the message after a
  586. * successful receive. The type of this value must match the value
  587. * transmitted by the sender, unless the sender transmitted a packed
  588. * archive or skeleton: in these cases, the sender transmits a @c
  589. * packed_oarchive or @c packed_skeleton_oarchive and the
  590. * destination receives a @c packed_iarchive or @c
  591. * packed_skeleton_iarchive, respectively.
  592. *
  593. * @returns a @c request object that describes this communication.
  594. */
  595. template<typename T>
  596. request irecv(int source, int tag, T& value) const;
  597. /**
  598. * @brief Initiate receipt of an array of values from a remote process.
  599. *
  600. * This routine initiates a receive operation for an array of values
  601. * transmitted by process @p source with the given @p tag.
  602. *
  603. * @param source The process that will be sending data. This will
  604. * either be a process rank within the communicator or the
  605. * constant @c any_source, indicating that we can receive the
  606. * message from any process.
  607. *
  608. * @param tag The tag that matches a particular kind of message sent
  609. * by the source process. This may be any tag value permitted by @c
  610. * send. Alternatively, the argument may be the constant @c any_tag,
  611. * indicating that this receive matches a message with any tag.
  612. *
  613. * @param values Will contain the values in the message after a
  614. * successful receive. The type of these elements must match the
  615. * type of the elements transmitted by the sender.
  616. *
  617. * @param n The number of values that can be stored into the @p
  618. * values array. This shall not be smaller than the number of
  619. * elements transmitted by the sender.
  620. *
  621. * @returns a @c request object that describes this communication.
  622. */
  623. template<typename T>
  624. request irecv(int source, int tag, T* values, int n) const;
  625. /**
  626. * @brief Initiate receipt of a message from a remote process that
  627. * carries no data.
  628. *
  629. * This routine initiates a receive operation for a message from
  630. * process @p source with the given @p tag that carries no data.
  631. *
  632. * @param source The process that will be sending the message. This
  633. * will either be a process rank within the communicator or the
  634. * constant @c any_source, indicating that we can receive the
  635. * message from any process.
  636. *
  637. * @param tag The tag that matches a particular kind of message
  638. * sent by the source process. This may be any tag value permitted
  639. * by @c send. Alternatively, the argument may be the constant @c
  640. * any_tag, indicating that this receive matches a message with any
  641. * tag.
  642. *
  643. * @returns a @c request object that describes this communication.
  644. */
  645. request irecv(int source, int tag) const;
  646. /**
  647. * @brief Waits until a message is available to be received.
  648. *
  649. * This operation waits until a message matching (@p source, @p tag)
  650. * is available to be received. It then returns information about
  651. * that message. The functionality is equivalent to @c MPI_Probe. To
  652. * check if a message is available without blocking, use @c iprobe.
  653. *
  654. * @param source Determine if there is a message available from
  655. * this rank. If @c any_source, then the message returned may come
  656. * from any source.
  657. *
  658. * @param tag Determine if there is a message available with the
  659. * given tag. If @c any_tag, then the message returned may have any
  660. * tag.
  661. *
  662. * @returns Returns information about the first message that
  663. * matches the given criteria.
  664. */
  665. status probe(int source = any_source, int tag = any_tag) const;
  666. /**
  667. * @brief Determine if a message is available to be received.
  668. *
  669. * This operation determines if a message matching (@p source, @p
  670. * tag) is available to be received. If so, it returns information
  671. * about that message; otherwise, it returns immediately with an
  672. * empty optional. The functionality is equivalent to @c
  673. * MPI_Iprobe. To wait until a message is available, use @c wait.
  674. *
  675. * @param source Determine if there is a message available from
  676. * this rank. If @c any_source, then the message returned may come
  677. * from any source.
  678. *
  679. * @param tag Determine if there is a message available with the
  680. * given tag. If @c any_tag, then the message returned may have any
  681. * tag.
  682. *
  683. * @returns If a matching message is available, returns
  684. * information about that message. Otherwise, returns an empty
  685. * @c boost::optional.
  686. */
  687. optional<status>
  688. iprobe(int source = any_source, int tag = any_tag) const;
  689. #ifdef barrier
  690. // Linux defines a function-like macro named "barrier". So, we need
  691. // to avoid expanding the macro when we define our barrier()
  692. // function. However, some C++ parsers (Doxygen, for instance) can't
  693. // handle this syntax, so we only use it when necessary.
  694. void (barrier)() const;
  695. #else
  696. /**
  697. * @brief Wait for all processes within a communicator to reach the
  698. * barrier.
  699. *
  700. * This routine is a collective operation that blocks each process
  701. * until all processes have entered it, then releases all of the
  702. * processes "simultaneously". It is equivalent to @c MPI_Barrier.
  703. */
  704. void barrier() const;
  705. #endif
  706. /** @brief Determine if this communicator is valid for
  707. * communication.
  708. *
  709. * Evaluates @c true in a boolean context if this communicator is
  710. * valid for communication, i.e., does not represent
  711. * MPI_COMM_NULL. Otherwise, evaluates @c false.
  712. */
  713. operator bool() const { return (bool)comm_ptr; }
  714. /**
  715. * @brief Access the MPI communicator associated with a Boost.MPI
  716. * communicator.
  717. *
  718. * This routine permits the implicit conversion from a Boost.MPI
  719. * communicator to an MPI communicator.
  720. *
  721. * @returns The associated MPI communicator.
  722. */
  723. operator MPI_Comm() const;
  724. /**
  725. * Split the communicator into multiple, disjoint communicators
  726. * each of which is based on a particular color. This is a
  727. * collective operation that returns a new communicator that is a
  728. * subgroup of @p this. This routine is functionally equivalent to
  729. * @c MPI_Comm_split.
  730. *
  731. * @param color The color of this process. All processes with the
  732. * same @p color value will be placed into the same group.
  733. *
  734. * @returns A new communicator containing all of the processes in
  735. * @p this that have the same @p color.
  736. */
  737. communicator split(int color) const;
  738. /**
  739. * Split the communicator into multiple, disjoint communicators
  740. * each of which is based on a particular color. This is a
  741. * collective operation that returns a new communicator that is a
  742. * subgroup of @p this. This routine is functionally equivalent to
  743. * @c MPI_Comm_split.
  744. *
  745. * @param color The color of this process. All processes with the
  746. * same @p color value will be placed into the same group.
  747. *
  748. * @param key A key value that will be used to determine the
  749. * ordering of processes with the same color in the resulting
  750. * communicator. If omitted, the rank of the processes in @p this
  751. * will determine the ordering of processes in the resulting
  752. * group.
  753. *
  754. * @returns A new communicator containing all of the processes in
  755. * @p this that have the same @p color.
  756. */
  757. communicator split(int color, int key) const;
  758. /**
  759. * Determine if the communicator is in fact an intercommunicator
  760. * and, if so, return that intercommunicator.
  761. *
  762. * @returns an @c optional containing the intercommunicator, if this
  763. * communicator is in fact an intercommunicator. Otherwise, returns
  764. * an empty @c optional.
  765. */
  766. optional<intercommunicator> as_intercommunicator() const;
  767. /**
  768. * Determine if the communicator has a graph topology and, if so,
  769. * return that @c graph_communicator. Even though the communicators
  770. * have different types, they refer to the same underlying
  771. * communication space and can be used interchangeably for
  772. * communication.
  773. *
  774. * @returns an @c optional containing the graph communicator, if this
  775. * communicator does in fact have a graph topology. Otherwise, returns
  776. * an empty @c optional.
  777. */
  778. optional<graph_communicator> as_graph_communicator() const;
  779. /**
  780. * Determines whether this communicator has a Cartesian topology.
  781. */
  782. bool has_cartesian_topology() const;
  783. #if 0
  784. template<typename Extents>
  785. communicator
  786. with_cartesian_topology(const Extents& extents,
  787. bool periodic = false,
  788. bool reorder = false) const;
  789. template<typename DimInputIterator, typename PeriodicInputIterator>
  790. communicator
  791. with_cartesian_topology(DimInputIterator first_dim,
  792. DimInputIterator last_dim,
  793. PeriodicInputIterator first_periodic,
  794. bool reorder = false);
  795. template<typename Allocator, std::size_t NumDims>
  796. communicator
  797. with_cartesian_topology(const multi_array<bool, NumDims, Allocator>& periods,
  798. bool reorder = false);
  799. #endif
  800. /** Abort all tasks in the group of this communicator.
  801. *
  802. * Makes a "best attempt" to abort all of the tasks in the group of
  803. * this communicator. Depending on the underlying MPI
  804. * implementation, this may either abort the entire program (and
  805. * possibly return @p errcode to the environment) or only abort
  806. * some processes, allowing the others to continue. Consult the
  807. * documentation for your MPI implementation. This is equivalent to
  808. * a call to @c MPI_Abort
  809. *
  810. * @param errcode The error code to return from aborted processes.
  811. * @returns Will not return.
  812. */
  813. void abort(int errcode) const;
  814. protected:
  815. /**
  816. * INTERNAL ONLY
  817. *
  818. * Implementation of sendrecv for mpi type.
  819. */
  820. template<typename T>
  821. status sendrecv_impl(int dest, int stag, const T& sval, int src, int rtag, T& rval,
  822. mpl::true_) const;
  823. /**
  824. * INTERNAL ONLY
  825. *
  826. * Implementation of sendrecv for complex types, which must be passed as archives.
  827. */
  828. template<typename T>
  829. status sendrecv_impl(int dest, int stag, const T& sval, int src, int rtag, T& rval,
  830. mpl::false_) const;
  831. /**
  832. * INTERNAL ONLY
  833. *
  834. * Function object that frees an MPI communicator and deletes the
  835. * memory associated with it. Intended to be used as a deleter with
  836. * shared_ptr.
  837. */
  838. struct comm_free
  839. {
  840. void operator()(MPI_Comm* comm) const
  841. {
  842. BOOST_ASSERT( comm != 0 );
  843. BOOST_ASSERT(*comm != MPI_COMM_NULL);
  844. int finalized;
  845. BOOST_MPI_CHECK_RESULT(MPI_Finalized, (&finalized));
  846. if (!finalized)
  847. BOOST_MPI_CHECK_RESULT(MPI_Comm_free, (comm));
  848. delete comm;
  849. }
  850. };
  851. /**
  852. * INTERNAL ONLY
  853. *
  854. * We're sending a type that has an associated MPI datatype, so we
  855. * map directly to that datatype.
  856. */
  857. template<typename T>
  858. void send_impl(int dest, int tag, const T& value, mpl::true_) const;
  859. /**
  860. * INTERNAL ONLY
  861. *
  862. * We're sending a type that does not have an associated MPI
  863. * datatype, so it must be serialized then sent as MPI_PACKED data,
  864. * to be deserialized on the receiver side.
  865. */
  866. template<typename T>
  867. void send_impl(int dest, int tag, const T& value, mpl::false_) const;
  868. /**
  869. * INTERNAL ONLY
  870. *
  871. * We're sending an array of a type that has an associated MPI
  872. * datatype, so we map directly to that datatype.
  873. */
  874. template<typename T>
  875. void
  876. array_send_impl(int dest, int tag, const T* values, int n, mpl::true_) const;
  877. /**
  878. * INTERNAL ONLY
  879. *
  880. * We're sending an array of a type that does not have an associated
  881. * MPI datatype, so it must be serialized then sent as MPI_PACKED
  882. * data, to be deserialized on the receiver side.
  883. */
  884. template<typename T>
  885. void
  886. array_send_impl(int dest, int tag, const T* values, int n,
  887. mpl::false_) const;
  888. /**
  889. * INTERNAL ONLY
  890. *
  891. * We're sending a type that has an associated MPI datatype, so we
  892. * map directly to that datatype.
  893. */
  894. template<typename T>
  895. request isend_impl(int dest, int tag, const T& value, mpl::true_) const;
  896. /**
  897. * INTERNAL ONLY
  898. *
  899. * We're sending a type that does not have an associated MPI
  900. * datatype, so it must be serialized then sent as MPI_PACKED data,
  901. * to be deserialized on the receiver side.
  902. */
  903. template<typename T>
  904. request isend_impl(int dest, int tag, const T& value, mpl::false_) const;
  905. /**
  906. * INTERNAL ONLY
  907. *
  908. * We're sending an array of a type that has an associated MPI
  909. * datatype, so we map directly to that datatype.
  910. */
  911. template<typename T>
  912. request
  913. array_isend_impl(int dest, int tag, const T* values, int n,
  914. mpl::true_) const;
  915. /**
  916. * INTERNAL ONLY
  917. *
  918. * We're sending an array of a type that does not have an associated
  919. * MPI datatype, so it must be serialized then sent as MPI_PACKED
  920. * data, to be deserialized on the receiver side.
  921. */
  922. template<typename T>
  923. request
  924. array_isend_impl(int dest, int tag, const T* values, int n,
  925. mpl::false_) const;
  926. /**
  927. * INTERNAL ONLY
  928. *
  929. * We're receiving a type that has an associated MPI datatype, so we
  930. * map directly to that datatype.
  931. */
  932. template<typename T>
  933. status recv_impl(int source, int tag, T& value, mpl::true_) const;
  934. /**
  935. * INTERNAL ONLY
  936. *
  937. * We're receiving a type that does not have an associated MPI
  938. * datatype, so it must have been serialized then sent as
  939. * MPI_PACKED. We'll receive it and then deserialize.
  940. */
  941. template<typename T>
  942. status recv_impl(int source, int tag, T& value, mpl::false_) const;
  943. /**
  944. * INTERNAL ONLY
  945. *
  946. * We're receiving an array of a type that has an associated MPI
  947. * datatype, so we map directly to that datatype.
  948. */
  949. template<typename T>
  950. status
  951. array_recv_impl(int source, int tag, T* values, int n, mpl::true_) const;
  952. /**
  953. * INTERNAL ONLY
  954. *
  955. * We're receiving a type that does not have an associated MPI
  956. * datatype, so it must have been serialized then sent as
  957. * MPI_PACKED. We'll receive it and then deserialize.
  958. */
  959. template<typename T>
  960. status
  961. array_recv_impl(int source, int tag, T* values, int n, mpl::false_) const;
  962. /**
  963. * INTERNAL ONLY
  964. *
  965. * We're receiving a type that has an associated MPI datatype, so we
  966. * map directly to that datatype.
  967. */
  968. template<typename T>
  969. request irecv_impl(int source, int tag, T& value, mpl::true_) const;
  970. /**
  971. * INTERNAL ONLY
  972. *
  973. * We're receiving a type that does not have an associated MPI
  974. * datatype, so it must have been serialized then sent as
  975. * MPI_PACKED. We'll receive it and then deserialize.
  976. */
  977. template<typename T>
  978. request irecv_impl(int source, int tag, T& value, mpl::false_) const;
  979. /**
  980. * INTERNAL ONLY
  981. *
  982. * We're receiving a type that has an associated MPI datatype, so we
  983. * map directly to that datatype.
  984. */
  985. template<typename T>
  986. request
  987. array_irecv_impl(int source, int tag, T* values, int n, mpl::true_) const;
  988. /**
  989. * INTERNAL ONLY
  990. *
  991. * We're receiving a type that does not have an associated MPI
  992. * datatype, so it must have been serialized then sent as
  993. * MPI_PACKED. We'll receive it and then deserialize.
  994. */
  995. template<typename T>
  996. request
  997. array_irecv_impl(int source, int tag, T* values, int n, mpl::false_) const;
  998. shared_ptr<MPI_Comm> comm_ptr;
  999. };
  1000. /**
  1001. * @brief Determines whether two communicators are identical.
  1002. *
  1003. * Equivalent to calling @c MPI_Comm_compare and checking whether the
  1004. * result is @c MPI_IDENT.
  1005. *
  1006. * @returns True when the two communicators refer to the same
  1007. * underlying MPI communicator.
  1008. */
  1009. BOOST_MPI_DECL bool operator==(const communicator& comm1, const communicator& comm2);
  1010. /**
  1011. * @brief Determines whether two communicators are different.
  1012. *
  1013. * @returns @c !(comm1 == comm2)
  1014. */
  1015. inline bool operator!=(const communicator& comm1, const communicator& comm2)
  1016. {
  1017. return !(comm1 == comm2);
  1018. }
  1019. /************************************************************************
  1020. * Implementation details *
  1021. ************************************************************************/
  1022. // Count elements in a message
  1023. template<typename T>
  1024. inline optional<int> status::count() const
  1025. {
  1026. return count_impl<T>(is_mpi_datatype<T>());
  1027. }
  1028. template<typename T>
  1029. optional<int> status::count_impl(mpl::true_) const
  1030. {
  1031. if (m_count != -1)
  1032. return m_count;
  1033. int return_value;
  1034. BOOST_MPI_CHECK_RESULT(MPI_Get_count,
  1035. (&m_status, get_mpi_datatype<T>(T()), &return_value));
  1036. if (return_value == MPI_UNDEFINED)
  1037. return optional<int>();
  1038. else
  1039. /* Cache the result. */
  1040. return m_count = return_value;
  1041. }
  1042. template<typename T>
  1043. inline optional<int> status::count_impl(mpl::false_) const
  1044. {
  1045. if (m_count == -1)
  1046. return optional<int>();
  1047. else
  1048. return m_count;
  1049. }
  1050. // We're sending a type that has an associated MPI datatype, so we
  1051. // map directly to that datatype.
  1052. template<typename T>
  1053. void
  1054. communicator::send_impl(int dest, int tag, const T& value, mpl::true_) const
  1055. {
  1056. BOOST_MPI_CHECK_RESULT(MPI_Send,
  1057. (const_cast<T*>(&value), 1, get_mpi_datatype<T>(value),
  1058. dest, tag, MPI_Comm(*this)));
  1059. }
  1060. // We're sending a type that does not have an associated MPI
  1061. // datatype, so it must be serialized then sent as MPI_PACKED data,
  1062. // to be deserialized on the receiver side.
  1063. template<typename T>
  1064. void
  1065. communicator::send_impl(int dest, int tag, const T& value, mpl::false_) const
  1066. {
  1067. packed_oarchive oa(*this);
  1068. oa << value;
  1069. send(dest, tag, oa);
  1070. }
  1071. // Single-element receive may either send the element directly or
  1072. // serialize it via a buffer.
  1073. template<typename T>
  1074. void communicator::send(int dest, int tag, const T& value) const
  1075. {
  1076. this->send_impl(dest, tag, value, is_mpi_datatype<T>());
  1077. }
  1078. // We're sending an array of a type that has an associated MPI
  1079. // datatype, so we map directly to that datatype.
  1080. template<typename T>
  1081. void
  1082. communicator::array_send_impl(int dest, int tag, const T* values, int n,
  1083. mpl::true_) const
  1084. {
  1085. BOOST_MPI_CHECK_RESULT(MPI_Send,
  1086. (const_cast<T*>(values), n,
  1087. get_mpi_datatype<T>(*values),
  1088. dest, tag, MPI_Comm(*this)));
  1089. }
  1090. // We're sending an array of a type that does not have an associated
  1091. // MPI datatype, so it must be serialized then sent as MPI_PACKED
  1092. // data, to be deserialized on the receiver side.
  1093. template<typename T>
  1094. void
  1095. communicator::array_send_impl(int dest, int tag, const T* values, int n,
  1096. mpl::false_) const
  1097. {
  1098. packed_oarchive oa(*this);
  1099. oa << n << boost::serialization::make_array(values, n);
  1100. send(dest, tag, oa);
  1101. }
  1102. // Array send must send the elements directly
  1103. template<typename T>
  1104. void communicator::send(int dest, int tag, const T* values, int n) const
  1105. {
  1106. this->array_send_impl(dest, tag, values, n, is_mpi_datatype<T>());
  1107. }
  1108. // We're receiving a type that has an associated MPI datatype, so we
  1109. // map directly to that datatype.
  1110. template<typename T>
  1111. status communicator::recv_impl(int source, int tag, T& value, mpl::true_) const
  1112. {
  1113. status stat;
  1114. BOOST_MPI_CHECK_RESULT(MPI_Recv,
  1115. (const_cast<T*>(&value), 1,
  1116. get_mpi_datatype<T>(value),
  1117. source, tag, MPI_Comm(*this), &stat.m_status));
  1118. return stat;
  1119. }
  1120. template<typename T>
  1121. status
  1122. communicator::recv_impl(int source, int tag, T& value, mpl::false_) const
  1123. {
  1124. // Receive the message
  1125. packed_iarchive ia(*this);
  1126. status stat = recv(source, tag, ia);
  1127. // Deserialize the data in the message
  1128. ia >> value;
  1129. return stat;
  1130. }
  1131. // Single-element receive may either receive the element directly or
  1132. // deserialize it from a buffer.
  1133. template<typename T>
  1134. status communicator::recv(int source, int tag, T& value) const
  1135. {
  1136. return this->recv_impl(source, tag, value, is_mpi_datatype<T>());
  1137. }
  1138. template<typename T>
  1139. status
  1140. communicator::array_recv_impl(int source, int tag, T* values, int n,
  1141. mpl::true_) const
  1142. {
  1143. status stat;
  1144. BOOST_MPI_CHECK_RESULT(MPI_Recv,
  1145. (const_cast<T*>(values), n,
  1146. get_mpi_datatype<T>(*values),
  1147. source, tag, MPI_Comm(*this), &stat.m_status));
  1148. return stat;
  1149. }
  1150. template<typename T>
  1151. status
  1152. communicator::array_recv_impl(int source, int tag, T* values, int n,
  1153. mpl::false_) const
  1154. {
  1155. // Receive the message
  1156. packed_iarchive ia(*this);
  1157. status stat = recv(source, tag, ia);
  1158. // Determine how much data we are going to receive
  1159. int count;
  1160. ia >> count;
  1161. // Deserialize the data in the message
  1162. boost::serialization::array_wrapper<T> arr(values, count > n? n : count);
  1163. ia >> arr;
  1164. if (count > n) {
  1165. boost::throw_exception(
  1166. std::range_error("communicator::recv: message receive overflow"));
  1167. }
  1168. stat.m_count = count;
  1169. return stat;
  1170. }
  1171. // Array receive must receive the elements directly into a buffer.
  1172. template<typename T>
  1173. status communicator::recv(int source, int tag, T* values, int n) const
  1174. {
  1175. return this->array_recv_impl(source, tag, values, n, is_mpi_datatype<T>());
  1176. }
  1177. template<typename T>
  1178. status communicator::sendrecv_impl(int dest, int stag, const T& sval, int src, int rtag, T& rval,
  1179. mpl::true_) const
  1180. {
  1181. status stat;
  1182. BOOST_MPI_CHECK_RESULT(MPI_Sendrecv,
  1183. (const_cast<T*>(&sval), 1,
  1184. get_mpi_datatype<T>(sval),
  1185. dest, stag,
  1186. &rval, 1,
  1187. get_mpi_datatype<T>(rval),
  1188. src, rtag,
  1189. MPI_Comm(*this), &stat.m_status));
  1190. return stat;
  1191. }
  1192. template<typename T>
  1193. status communicator::sendrecv_impl(int dest, int stag, const T& sval, int src, int rtag, T& rval,
  1194. mpl::false_) const
  1195. {
  1196. int const SEND = 0;
  1197. int const RECV = 1;
  1198. request srrequests[2];
  1199. srrequests[SEND] = this->isend_impl(dest, stag, sval, mpl::false_());
  1200. srrequests[RECV] = this->irecv_impl(src, rtag, rval, mpl::false_());
  1201. status srstatuses[2];
  1202. wait_all(srrequests, srrequests + 2, srstatuses);
  1203. return srstatuses[RECV];
  1204. }
  1205. template<typename T>
  1206. status communicator::sendrecv(int dest, int stag, const T& sval, int src, int rtag, T& rval) const
  1207. {
  1208. return this->sendrecv_impl(dest, stag, sval, src, rtag, rval, is_mpi_datatype<T>());
  1209. }
  1210. // We're sending a type that has an associated MPI datatype, so we
  1211. // map directly to that datatype.
  1212. template<typename T>
  1213. request
  1214. communicator::isend_impl(int dest, int tag, const T& value, mpl::true_) const
  1215. {
  1216. request req;
  1217. BOOST_MPI_CHECK_RESULT(MPI_Isend,
  1218. (const_cast<T*>(&value), 1,
  1219. get_mpi_datatype<T>(value),
  1220. dest, tag, MPI_Comm(*this), &req.m_requests[0]));
  1221. return req;
  1222. }
  1223. // We're sending a type that does not have an associated MPI
  1224. // datatype, so it must be serialized then sent as MPI_PACKED data,
  1225. // to be deserialized on the receiver side.
  1226. template<typename T>
  1227. request
  1228. communicator::isend_impl(int dest, int tag, const T& value, mpl::false_) const
  1229. {
  1230. shared_ptr<packed_oarchive> archive(new packed_oarchive(*this));
  1231. *archive << value;
  1232. request result = isend(dest, tag, *archive);
  1233. result.m_data = archive;
  1234. return result;
  1235. }
  1236. // Single-element receive may either send the element directly or
  1237. // serialize it via a buffer.
  1238. template<typename T>
  1239. request communicator::isend(int dest, int tag, const T& value) const
  1240. {
  1241. return this->isend_impl(dest, tag, value, is_mpi_datatype<T>());
  1242. }
  1243. template<typename T>
  1244. request
  1245. communicator::array_isend_impl(int dest, int tag, const T* values, int n,
  1246. mpl::true_) const
  1247. {
  1248. request req;
  1249. BOOST_MPI_CHECK_RESULT(MPI_Isend,
  1250. (const_cast<T*>(values), n,
  1251. get_mpi_datatype<T>(*values),
  1252. dest, tag, MPI_Comm(*this), &req.m_requests[0]));
  1253. return req;
  1254. }
  1255. template<typename T>
  1256. request
  1257. communicator::array_isend_impl(int dest, int tag, const T* values, int n,
  1258. mpl::false_) const
  1259. {
  1260. shared_ptr<packed_oarchive> archive(new packed_oarchive(*this));
  1261. *archive << n << boost::serialization::make_array(values, n);
  1262. request result = isend(dest, tag, *archive);
  1263. result.m_data = archive;
  1264. return result;
  1265. }
  1266. // Array isend must send the elements directly
  1267. template<typename T>
  1268. request communicator::isend(int dest, int tag, const T* values, int n) const
  1269. {
  1270. return array_isend_impl(dest, tag, values, n, is_mpi_datatype<T>());
  1271. }
  1272. namespace detail {
  1273. /**
  1274. * Internal data structure that stores everything required to manage
  1275. * the receipt of serialized data via a request object.
  1276. */
  1277. template<typename T>
  1278. struct serialized_irecv_data
  1279. {
  1280. serialized_irecv_data(const communicator& comm, int source, int tag,
  1281. T& value)
  1282. : comm(comm), source(source), tag(tag), ia(comm), value(value)
  1283. {
  1284. }
  1285. void deserialize(status& stat)
  1286. {
  1287. ia >> value;
  1288. stat.m_count = 1;
  1289. }
  1290. communicator comm;
  1291. int source;
  1292. int tag;
  1293. std::size_t count;
  1294. packed_iarchive ia;
  1295. T& value;
  1296. };
  1297. template<>
  1298. struct serialized_irecv_data<packed_iarchive>
  1299. {
  1300. serialized_irecv_data(const communicator& comm, int source, int tag,
  1301. packed_iarchive& ia)
  1302. : comm(comm), source(source), tag(tag), ia(ia) { }
  1303. void deserialize(status&) { /* Do nothing. */ }
  1304. communicator comm;
  1305. int source;
  1306. int tag;
  1307. std::size_t count;
  1308. packed_iarchive& ia;
  1309. };
  1310. /**
  1311. * Internal data structure that stores everything required to manage
  1312. * the receipt of an array of serialized data via a request object.
  1313. */
  1314. template<typename T>
  1315. struct serialized_array_irecv_data
  1316. {
  1317. serialized_array_irecv_data(const communicator& comm, int source, int tag,
  1318. T* values, int n)
  1319. : comm(comm), source(source), tag(tag), ia(comm), values(values), n(n)
  1320. {
  1321. }
  1322. void deserialize(status& stat);
  1323. communicator comm;
  1324. int source;
  1325. int tag;
  1326. std::size_t count;
  1327. packed_iarchive ia;
  1328. T* values;
  1329. int n;
  1330. };
  1331. template<typename T>
  1332. void serialized_array_irecv_data<T>::deserialize(status& stat)
  1333. {
  1334. // Determine how much data we are going to receive
  1335. int count;
  1336. ia >> count;
  1337. // Deserialize the data in the message
  1338. boost::serialization::array_wrapper<T> arr(values, count > n? n : count);
  1339. ia >> arr;
  1340. if (count > n) {
  1341. boost::throw_exception(
  1342. std::range_error("communicator::recv: message receive overflow"));
  1343. }
  1344. stat.m_count = count;
  1345. }
  1346. }
  1347. template<typename T>
  1348. optional<status>
  1349. request::handle_serialized_irecv(request* self, request_action action)
  1350. {
  1351. typedef detail::serialized_irecv_data<T> data_t;
  1352. shared_ptr<data_t> data = static_pointer_cast<data_t>(self->m_data);
  1353. if (action == ra_wait) {
  1354. status stat;
  1355. if (self->m_requests[1] == MPI_REQUEST_NULL) {
  1356. // Wait for the count message to complete
  1357. BOOST_MPI_CHECK_RESULT(MPI_Wait,
  1358. (self->m_requests, &stat.m_status));
  1359. // Resize our buffer and get ready to receive its data
  1360. data->ia.resize(data->count);
  1361. BOOST_MPI_CHECK_RESULT(MPI_Irecv,
  1362. (data->ia.address(), data->ia.size(), MPI_PACKED,
  1363. stat.source(), stat.tag(),
  1364. MPI_Comm(data->comm), self->m_requests + 1));
  1365. }
  1366. // Wait until we have received the entire message
  1367. BOOST_MPI_CHECK_RESULT(MPI_Wait,
  1368. (self->m_requests + 1, &stat.m_status));
  1369. data->deserialize(stat);
  1370. return stat;
  1371. } else if (action == ra_test) {
  1372. status stat;
  1373. int flag = 0;
  1374. if (self->m_requests[1] == MPI_REQUEST_NULL) {
  1375. // Check if the count message has completed
  1376. BOOST_MPI_CHECK_RESULT(MPI_Test,
  1377. (self->m_requests, &flag, &stat.m_status));
  1378. if (flag) {
  1379. // Resize our buffer and get ready to receive its data
  1380. data->ia.resize(data->count);
  1381. BOOST_MPI_CHECK_RESULT(MPI_Irecv,
  1382. (data->ia.address(), data->ia.size(),MPI_PACKED,
  1383. stat.source(), stat.tag(),
  1384. MPI_Comm(data->comm), self->m_requests + 1));
  1385. } else
  1386. return optional<status>(); // We have not finished yet
  1387. }
  1388. // Check if we have received the message data
  1389. BOOST_MPI_CHECK_RESULT(MPI_Test,
  1390. (self->m_requests + 1, &flag, &stat.m_status));
  1391. if (flag) {
  1392. data->deserialize(stat);
  1393. return stat;
  1394. } else
  1395. return optional<status>();
  1396. } else {
  1397. return optional<status>();
  1398. }
  1399. }
  1400. template<typename T>
  1401. optional<status>
  1402. request::handle_serialized_array_irecv(request* self, request_action action)
  1403. {
  1404. typedef detail::serialized_array_irecv_data<T> data_t;
  1405. shared_ptr<data_t> data = static_pointer_cast<data_t>(self->m_data);
  1406. if (action == ra_wait) {
  1407. status stat;
  1408. if (self->m_requests[1] == MPI_REQUEST_NULL) {
  1409. // Wait for the count message to complete
  1410. BOOST_MPI_CHECK_RESULT(MPI_Wait,
  1411. (self->m_requests, &stat.m_status));
  1412. // Resize our buffer and get ready to receive its data
  1413. data->ia.resize(data->count);
  1414. BOOST_MPI_CHECK_RESULT(MPI_Irecv,
  1415. (data->ia.address(), data->ia.size(), MPI_PACKED,
  1416. stat.source(), stat.tag(),
  1417. MPI_Comm(data->comm), self->m_requests + 1));
  1418. }
  1419. // Wait until we have received the entire message
  1420. BOOST_MPI_CHECK_RESULT(MPI_Wait,
  1421. (self->m_requests + 1, &stat.m_status));
  1422. data->deserialize(stat);
  1423. return stat;
  1424. } else if (action == ra_test) {
  1425. status stat;
  1426. int flag = 0;
  1427. if (self->m_requests[1] == MPI_REQUEST_NULL) {
  1428. // Check if the count message has completed
  1429. BOOST_MPI_CHECK_RESULT(MPI_Test,
  1430. (self->m_requests, &flag, &stat.m_status));
  1431. if (flag) {
  1432. // Resize our buffer and get ready to receive its data
  1433. data->ia.resize(data->count);
  1434. BOOST_MPI_CHECK_RESULT(MPI_Irecv,
  1435. (data->ia.address(), data->ia.size(),MPI_PACKED,
  1436. stat.source(), stat.tag(),
  1437. MPI_Comm(data->comm), self->m_requests + 1));
  1438. } else
  1439. return optional<status>(); // We have not finished yet
  1440. }
  1441. // Check if we have received the message data
  1442. BOOST_MPI_CHECK_RESULT(MPI_Test,
  1443. (self->m_requests + 1, &flag, &stat.m_status));
  1444. if (flag) {
  1445. data->deserialize(stat);
  1446. return stat;
  1447. } else
  1448. return optional<status>();
  1449. } else {
  1450. return optional<status>();
  1451. }
  1452. }
  1453. // We're receiving a type that has an associated MPI datatype, so we
  1454. // map directly to that datatype.
  1455. template<typename T>
  1456. request
  1457. communicator::irecv_impl(int source, int tag, T& value, mpl::true_) const
  1458. {
  1459. request req;
  1460. BOOST_MPI_CHECK_RESULT(MPI_Irecv,
  1461. (const_cast<T*>(&value), 1,
  1462. get_mpi_datatype<T>(value),
  1463. source, tag, MPI_Comm(*this), &req.m_requests[0]));
  1464. return req;
  1465. }
  1466. template<typename T>
  1467. request
  1468. communicator::irecv_impl(int source, int tag, T& value, mpl::false_) const
  1469. {
  1470. typedef detail::serialized_irecv_data<T> data_t;
  1471. shared_ptr<data_t> data(new data_t(*this, source, tag, value));
  1472. request req;
  1473. req.m_data = data;
  1474. req.m_handler = request::handle_serialized_irecv<T>;
  1475. BOOST_MPI_CHECK_RESULT(MPI_Irecv,
  1476. (&data->count, 1,
  1477. get_mpi_datatype<std::size_t>(data->count),
  1478. source, tag, MPI_Comm(*this), &req.m_requests[0]));
  1479. return req;
  1480. }
  1481. template<typename T>
  1482. request
  1483. communicator::irecv(int source, int tag, T& value) const
  1484. {
  1485. return this->irecv_impl(source, tag, value, is_mpi_datatype<T>());
  1486. }
  1487. template<typename T>
  1488. request
  1489. communicator::array_irecv_impl(int source, int tag, T* values, int n,
  1490. mpl::true_) const
  1491. {
  1492. request req;
  1493. BOOST_MPI_CHECK_RESULT(MPI_Irecv,
  1494. (const_cast<T*>(values), n,
  1495. get_mpi_datatype<T>(*values),
  1496. source, tag, MPI_Comm(*this), &req.m_requests[0]));
  1497. return req;
  1498. }
  1499. template<typename T>
  1500. request
  1501. communicator::array_irecv_impl(int source, int tag, T* values, int n,
  1502. mpl::false_) const
  1503. {
  1504. typedef detail::serialized_array_irecv_data<T> data_t;
  1505. shared_ptr<data_t> data(new data_t(*this, source, tag, values, n));
  1506. request req;
  1507. req.m_data = data;
  1508. req.m_handler = request::handle_serialized_array_irecv<T>;
  1509. BOOST_MPI_CHECK_RESULT(MPI_Irecv,
  1510. (&data->count, 1,
  1511. get_mpi_datatype<std::size_t>(data->count),
  1512. source, tag, MPI_Comm(*this), &req.m_requests[0]));
  1513. return req;
  1514. }
  1515. // Array receive must receive the elements directly into a buffer.
  1516. template<typename T>
  1517. request communicator::irecv(int source, int tag, T* values, int n) const
  1518. {
  1519. return this->array_irecv_impl(source, tag, values, n, is_mpi_datatype<T>());
  1520. }
  1521. /**
  1522. * INTERNAL ONLY
  1523. */
  1524. template<>
  1525. BOOST_MPI_DECL void
  1526. communicator::send<packed_oarchive>(int dest, int tag,
  1527. const packed_oarchive& ar) const;
  1528. /**
  1529. * INTERNAL ONLY
  1530. */
  1531. template<>
  1532. BOOST_MPI_DECL void
  1533. communicator::send<packed_skeleton_oarchive>
  1534. (int dest, int tag, const packed_skeleton_oarchive& ar) const;
  1535. /**
  1536. * INTERNAL ONLY
  1537. */
  1538. template<>
  1539. BOOST_MPI_DECL void
  1540. communicator::send<content>(int dest, int tag, const content& c) const;
  1541. /**
  1542. * INTERNAL ONLY
  1543. */
  1544. template<>
  1545. BOOST_MPI_DECL status
  1546. communicator::recv<packed_iarchive>(int source, int tag,
  1547. packed_iarchive& ar) const;
  1548. /**
  1549. * INTERNAL ONLY
  1550. */
  1551. template<>
  1552. BOOST_MPI_DECL status
  1553. communicator::recv<packed_skeleton_iarchive>
  1554. (int source, int tag, packed_skeleton_iarchive& ar) const;
  1555. /**
  1556. * INTERNAL ONLY
  1557. */
  1558. template<>
  1559. BOOST_MPI_DECL status
  1560. communicator::recv<const content>(int source, int tag,
  1561. const content& c) const;
  1562. /**
  1563. * INTERNAL ONLY
  1564. */
  1565. template<>
  1566. inline status
  1567. communicator::recv<content>(int source, int tag,
  1568. content& c) const
  1569. {
  1570. return recv<const content>(source,tag,c);
  1571. }
  1572. /**
  1573. * INTERNAL ONLY
  1574. */
  1575. template<>
  1576. BOOST_MPI_DECL request
  1577. communicator::isend<packed_oarchive>(int dest, int tag,
  1578. const packed_oarchive& ar) const;
  1579. /**
  1580. * INTERNAL ONLY
  1581. */
  1582. template<>
  1583. BOOST_MPI_DECL request
  1584. communicator::isend<packed_skeleton_oarchive>
  1585. (int dest, int tag, const packed_skeleton_oarchive& ar) const;
  1586. /**
  1587. * INTERNAL ONLY
  1588. */
  1589. template<>
  1590. BOOST_MPI_DECL request
  1591. communicator::isend<content>(int dest, int tag, const content& c) const;
  1592. /**
  1593. * INTERNAL ONLY
  1594. */
  1595. template<>
  1596. BOOST_MPI_DECL request
  1597. communicator::irecv<packed_skeleton_iarchive>
  1598. (int source, int tag, packed_skeleton_iarchive& ar) const;
  1599. /**
  1600. * INTERNAL ONLY
  1601. */
  1602. template<>
  1603. BOOST_MPI_DECL request
  1604. communicator::irecv<const content>(int source, int tag,
  1605. const content& c) const;
  1606. /**
  1607. * INTERNAL ONLY
  1608. */
  1609. template<>
  1610. inline request
  1611. communicator::irecv<content>(int source, int tag,
  1612. content& c) const
  1613. {
  1614. return irecv<const content>(source, tag, c);
  1615. }
  1616. } } // end namespace boost::mpi
  1617. // If the user has already included skeleton_and_content.hpp, include
  1618. // the code to send/receive skeletons and content.
  1619. #ifdef BOOST_MPI_SKELETON_AND_CONTENT_HPP
  1620. # include <boost/mpi/detail/communicator_sc.hpp>
  1621. #endif
  1622. #ifdef BOOST_MSVC
  1623. # pragma warning(pop)
  1624. #endif
  1625. #endif // BOOST_MPI_COMMUNICATOR_HPP