Ticket #5245: boost_1_45_0.ssend.patch

File boost_1_45_0.ssend.patch, 40.2 KB (added by Riccardo Murri <riccardo.murri@…>, 12 years ago)

patch implementing ssend/issend functionality in Boost.MPI (applies to 1.45 and 1.46)

  • boost/mpi/communicator.hpp

    Only in boost_1_45_0: bjam
    diff -ruw -x '*~' -x '*.o' -x '*.a' boost_1_45_0.orig/boost/mpi/communicator.hpp boost_1_45_0/boost/mpi/communicator.hpp
    old new  
    296296   *
    297297   *  @param proxy The @c skeleton_proxy containing a reference to the
    298298   *  object whose skeleton will be transmitted.
    299    *
    300299   */
    301300  template<typename T>
    302301  void send(int dest, int tag, const skeleton_proxy<T>& proxy) const;
     
    344343   *  @param tag The tag that will be associated with this message. Tags
    345344   *  may be any integer between zero and an implementation-defined
    346345   *  upper limit. This limit is accessible via @c environment::max_tag().
    347    *
    348346   */
    349347  void send(int dest, int tag) const;
    350348
    351349  /**
     350   *  @brief Synchronously send data to another process.
     351   *
     352   *  This routine executes a potentially blocking synchronous send
     353   *  with tag @p tag to the process with rank @p dest. This routine
     354   *  is exactly equivalent to @ref send(int,int,const T&) (which see)
     355   *  but uses an MPI synchronous send (MPI_Ssend).
     356   *
     357   */
     358  template<typename T>
     359  void ssend(int dest, int tag, const T& value) const;
     360
     361  /**
     362   *  @brief Synchronously send the skeleton of an object.
     363   *
     364   *  This routine executes a potentially blocking send with tag @p
     365   *  tag to the process with rank @p dest. It can be received by the
     366   *  destination process with a matching @c recv call. This variation
     367   *  on @c ssend will be used when a synchronous send of a skeleton
     368   *  is explicitly requested via code such as:
     369   *
     370   *  @code
     371   *    comm.ssend(dest, tag, skeleton(object));
     372   *  @endcode
     373   *
     374   *  This routine is exactly equivalent to @ref send(int,int,const
     375   *  skeleton_proxy<T>&) (which see) but uses an MPI synchronous send
     376   *  (MPI_Ssend).
     377   *
     378   */
     379  template<typename T>
     380  void ssend(int dest, int tag, const skeleton_proxy<T>& proxy) const;
     381
     382  /**
     383   *  @brief Synchronously send an array of values to another process.
     384   *
     385   *  This routine is equivalent to @ref send(int,int,const T*,int)
     386   *  (which see) but uses an MPI synchronous send (MPI_Ssend).
     387   */
     388  template<typename T>
     389  void ssend(int dest, int tag, const T* values, int n) const;
     390
     391  /**
     392   *  @brief Synchronously send a message to another process without
     393   *  any data.
     394   *
     395   *  This routine is equivalent to @ref send(int,int) (which see) but
     396   *  uses an MPI synchronous send (MPI_Ssend).
     397   */
     398  void ssend(int dest, int tag) const;
     399
     400  /**
    352401   * @brief Receive data from a remote process.
    353402   *
    354403   * This routine blocks until it receives a message from the process @p
     
    586635   *  may be any integer between zero and an implementation-defined
    587636   *  upper limit. This limit is accessible via @c environment::max_tag().
    588637   *
    589    *
    590638   *  @returns a @c request object that describes this communication.
    591639   */
    592640  request isend(int dest, int tag) const;
    593641
    594642  /**
     643   *  @brief Synchronously send a message to a remote process without
     644   *  blocking.
     645   *
     646   *  This routine is equivalent to @ref isend(int,int,const T&)
     647   *  (which see) but uses an MPI synchronous send (MPI_Ssend).
     648   */
     649  template<typename T>
     650  request issend(int dest, int tag, const T& value) const;
     651
     652  /**
     653   *  @brief Synchronously send the skeleton of an object without blocking.
     654   *
     655   *  This routine is equivalent to @ref isend(int,int,const skeleton_proxy<T>&)
     656   *  (which see) but uses an MPI synchronous send (MPI_Ssend).
     657   */
     658  template<typename T>
     659  request issend(int dest, int tag, const skeleton_proxy<T>& proxy) const;
     660
     661  /**
     662   *  @brief Synchronously send an array of values to another process
     663   *  without blocking.
     664   *
     665   *  This routine is equivalent to @ref isend(int,int,const T*,int)
     666   *  (which see) but uses an MPI synchronous send (MPI_Ssend).
     667   */
     668  template<typename T>
     669  request issend(int dest, int tag, const T* values, int n) const;
     670
     671  /**
     672   *  @brief Synchronously send a message to another process without
     673   *  any data without blocking.
     674   *
     675   *  This routine is equivalent to @ref isend(int,int)
     676   *  (which see) but uses an MPI synchronous send (MPI_Ssend).
     677   */
     678  request issend(int dest, int tag) const;
     679
     680  /**
    595681   *  @brief Prepare to receive a message from a remote process.
    596682   *
    597683   *  The @c irecv method is functionally identical to the @c recv
     
    885971   * map directly to that datatype.
    886972   */
    887973  template<typename T>
    888   void send_impl(int dest, int tag, const T& value, mpl::true_) const;
     974  void send_impl(int dest, int tag, const T& value, mpl::true_,
     975                 const bool synchronous = false) const;
    889976
    890977  /**
    891978   * INTERNAL ONLY
     
    895982   * to be deserialized on the receiver side.
    896983   */
    897984  template<typename T>
    898   void send_impl(int dest, int tag, const T& value, mpl::false_) const;
     985  void send_impl(int dest, int tag, const T& value, mpl::false_,
     986                 const bool synchronous = false) const;
     987
     988  /**
     989   * INTERNAL ONLY
     990   */
     991  template<typename T>
     992  void send_impl(int dest, int tag, const skeleton_proxy<T>& proxy,
     993                 const bool synchronous) const;
    899994
    900995  /**
    901996   * INTERNAL ONLY
     
    9051000   */
    9061001  template<typename T>
    9071002  void
    908   array_send_impl(int dest, int tag, const T* values, int n, mpl::true_) const;
     1003  array_send_impl(int dest, int tag, const T* values, int n, mpl::true_,
     1004                  const bool synchronous = false) const;
    9091005
    9101006  /**
    9111007   * INTERNAL ONLY
     
    9171013  template<typename T>
    9181014  void
    9191015  array_send_impl(int dest, int tag, const T* values, int n,
    920                   mpl::false_) const;
     1016                  mpl::false_, const bool synchronous = false) const;
    9211017
    9221018  /**
    9231019   * INTERNAL ONLY
     
    9261022   * map directly to that datatype.
    9271023   */
    9281024  template<typename T>
    929   request isend_impl(int dest, int tag, const T& value, mpl::true_) const;
     1025  request isend_impl(int dest, int tag, const T& value, mpl::true_,
     1026                     const bool synchronous = false) const;
    9301027
    9311028  /**
    9321029   * INTERNAL ONLY
     
    9361033   * to be deserialized on the receiver side.
    9371034   */
    9381035  template<typename T>
    939   request isend_impl(int dest, int tag, const T& value, mpl::false_) const;
     1036  request isend_impl(int dest, int tag, const T& value, mpl::false_,
     1037                     const bool synchronous = false) const;
     1038
     1039  /**
     1040   * INTERNAL ONLY
     1041   */
     1042  template<typename T>
     1043  request isend_impl(int dest, int tag, const skeleton_proxy<T>& proxy,
     1044                     const bool synchronous) const;
    9401045
    9411046  /**
    9421047   * INTERNAL ONLY
     
    9471052  template<typename T>
    9481053  request
    9491054  array_isend_impl(int dest, int tag, const T* values, int n,
    950                    mpl::true_) const;
     1055                   mpl::true_, const bool synchronous = false) const;
    9511056
    9521057  /**
    9531058   * INTERNAL ONLY
     
    9591064  template<typename T>
    9601065  request
    9611066  array_isend_impl(int dest, int tag, const T* values, int n,
    962                    mpl::false_) const;
     1067                   mpl::false_, const bool synchronous = false) const;
    9631068
    9641069  /**
    9651070   * INTERNAL ONLY
     
    11051210// map directly to that datatype.
    11061211template<typename T>
    11071212void
    1108 communicator::send_impl(int dest, int tag, const T& value, mpl::true_) const
     1213communicator::send_impl(int dest, int tag, const T& value, mpl::true_,
     1214                        const bool synchronous) const
    11091215{
     1216  if (synchronous) {
     1217    BOOST_MPI_CHECK_RESULT(MPI_Ssend,
     1218                           (const_cast<T*>(&value), 1, get_mpi_datatype<T>(value),
     1219                            dest, tag, MPI_Comm(*this)));
     1220  } else {
    11101221  BOOST_MPI_CHECK_RESULT(MPI_Send,
    11111222                         (const_cast<T*>(&value), 1, get_mpi_datatype<T>(value),
    11121223                          dest, tag, MPI_Comm(*this)));
     1224  };
    11131225}
    11141226
    11151227// We're sending a type that does not have an associated MPI
     
    11171229// to be deserialized on the receiver side.
    11181230template<typename T>
    11191231void
    1120 communicator::send_impl(int dest, int tag, const T& value, mpl::false_) const
     1232communicator::send_impl(int dest, int tag, const T& value, mpl::false_,
     1233                        const bool synchronous) const
    11211234{
    11221235  packed_oarchive oa(*this);
    11231236  oa << value;
     1237  if (synchronous)
     1238    ssend(dest, tag, oa);
     1239  else
    11241240  send(dest, tag, oa);
    11251241}
    11261242
     
    11291245template<typename T>
    11301246void communicator::send(int dest, int tag, const T& value) const
    11311247{
    1132   this->send_impl(dest, tag, value, is_mpi_datatype<T>());
     1248  send_impl(dest, tag, value, is_mpi_datatype<T>(), false);
     1249}
     1250
     1251// Single-element receive may either send the element directly or
     1252// serialize it via a buffer.
     1253template<typename T>
     1254void communicator::ssend(int dest, int tag, const T& value) const
     1255{
     1256  send_impl(dest, tag, value, is_mpi_datatype<T>(), true);
    11331257}
    11341258
    11351259// We're sending an array of a type that has an associated MPI
     
    11371261template<typename T>
    11381262void
    11391263communicator::array_send_impl(int dest, int tag, const T* values, int n,
    1140                               mpl::true_) const
     1264                              mpl::true_, const bool synchronous) const
    11411265{
     1266  if (synchronous) {
     1267    BOOST_MPI_CHECK_RESULT(MPI_Ssend,
     1268                           (const_cast<T*>(values), n,
     1269                            get_mpi_datatype<T>(*values),
     1270                            dest, tag, MPI_Comm(*this)));
     1271  } else {
    11421272  BOOST_MPI_CHECK_RESULT(MPI_Send,
    11431273                         (const_cast<T*>(values), n,
    11441274                          get_mpi_datatype<T>(*values),
    11451275                          dest, tag, MPI_Comm(*this)));
     1276  };
    11461277}
    11471278
    11481279// We're sending an array of a type that does not have an associated
     
    11511282template<typename T>
    11521283void
    11531284communicator::array_send_impl(int dest, int tag, const T* values, int n,
    1154                               mpl::false_) const
     1285                              mpl::false_, const bool synchronous) const
    11551286{
    11561287  packed_oarchive oa(*this);
    11571288  oa << n << boost::serialization::make_array(values, n);
     1289  if (synchronous)
     1290    ssend(dest, tag, oa);
     1291  else
    11581292  send(dest, tag, oa);
    11591293}
    11601294
     
    11621296template<typename T>
    11631297void communicator::send(int dest, int tag, const T* values, int n) const
    11641298{
    1165   this->array_send_impl(dest, tag, values, n, is_mpi_datatype<T>());
     1299  this->array_send_impl(dest, tag, values, n, is_mpi_datatype<T>(), false);
     1300}
     1301
     1302// Array ssend must send the elements directly
     1303template<typename T>
     1304void communicator::ssend(int dest, int tag, const T* values, int n) const
     1305{
     1306  this->array_send_impl(dest, tag, values, n, is_mpi_datatype<T>(), true);
    11661307}
    11671308
    11681309// We're receiving a type that has an associated MPI datatype, so we
     
    12511392// map directly to that datatype.
    12521393template<typename T>
    12531394request
    1254 communicator::isend_impl(int dest, int tag, const T& value, mpl::true_) const
     1395communicator::isend_impl(int dest, int tag, const T& value, mpl::true_,
     1396                         const bool synchronous) const
    12551397{
    12561398  request req;
     1399  if (synchronous) {
     1400    BOOST_MPI_CHECK_RESULT(MPI_Issend,
     1401                           (const_cast<T*>(&value), 1,
     1402                            get_mpi_datatype<T>(value),
     1403                            dest, tag, MPI_Comm(*this), &req.m_requests[0]));
     1404  } else {
    12571405  BOOST_MPI_CHECK_RESULT(MPI_Isend,
    12581406                         (const_cast<T*>(&value), 1,
    12591407                          get_mpi_datatype<T>(value),
    12601408                          dest, tag, MPI_Comm(*this), &req.m_requests[0]));
     1409  };
    12611410  return req;
    12621411}
    12631412
     
    12661415// to be deserialized on the receiver side.
    12671416template<typename T>
    12681417request
    1269 communicator::isend_impl(int dest, int tag, const T& value, mpl::false_) const
     1418communicator::isend_impl(int dest, int tag, const T& value, mpl::false_,
     1419                         const bool synchronous) const
    12701420{
    12711421  shared_ptr<packed_oarchive> archive(new packed_oarchive(*this));
    12721422  *archive << value;
    1273   request result = isend(dest, tag, *archive);
     1423  request result = (synchronous?
     1424                    issend(dest, tag, *archive)
     1425                    : isend(dest, tag, *archive));
    12741426  result.m_data = archive;
    12751427  return result;
    12761428}
     
    12801432template<typename T>
    12811433request communicator::isend(int dest, int tag, const T& value) const
    12821434{
    1283   return this->isend_impl(dest, tag, value, is_mpi_datatype<T>());
     1435  return isend_impl(dest, tag, value, is_mpi_datatype<T>(), false);
     1436}
     1437
     1438// Single-element receive may either send the element directly or
     1439// serialize it via a buffer.
     1440template<typename T>
     1441request communicator::issend(int dest, int tag, const T& value) const
     1442{
     1443  return isend_impl(dest, tag, value, is_mpi_datatype<T>(), true);
    12841444}
    12851445
    12861446template<typename T>
    12871447request
    12881448communicator::array_isend_impl(int dest, int tag, const T* values, int n,
    1289                                mpl::true_) const
     1449                               mpl::true_, const bool synchronous) const
    12901450{
    12911451  request req;
     1452  if (synchronous) {
     1453    BOOST_MPI_CHECK_RESULT(MPI_Issend,
     1454                           (const_cast<T*>(values), n,
     1455                            get_mpi_datatype<T>(*values),
     1456                            dest, tag, MPI_Comm(*this), &req.m_requests[0]));
     1457  } else {
    12921458  BOOST_MPI_CHECK_RESULT(MPI_Isend,
    12931459                         (const_cast<T*>(values), n,
    12941460                          get_mpi_datatype<T>(*values),
    12951461                          dest, tag, MPI_Comm(*this), &req.m_requests[0]));
     1462  };
    12961463  return req;
    12971464}
    12981465
    12991466template<typename T>
    13001467request
    13011468communicator::array_isend_impl(int dest, int tag, const T* values, int n,
    1302                                mpl::false_) const
     1469                               mpl::false_, const bool synchronous) const
    13031470{
    13041471  shared_ptr<packed_oarchive> archive(new packed_oarchive(*this));
    13051472  *archive << n << boost::serialization::make_array(values, n);
    1306   request result = isend(dest, tag, *archive);
     1473  request result = (synchronous?
     1474                    issend(dest, tag, *archive)
     1475                    : isend(dest, tag, *archive));
    13071476  result.m_data = archive;
    13081477  return result;
    13091478}
     
    13131482template<typename T>
    13141483request communicator::isend(int dest, int tag, const T* values, int n) const
    13151484{
    1316   return array_isend_impl(dest, tag, values, n, is_mpi_datatype<T>());
     1485  return array_isend_impl(dest, tag, values, n, is_mpi_datatype<T>(), false);
     1486}
     1487
     1488// Array isend must send the elements directly
     1489template<typename T>
     1490request communicator::issend(int dest, int tag, const T* values, int n) const
     1491{
     1492  return array_isend_impl(dest, tag, values, n, is_mpi_datatype<T>(), true);
    13171493}
    13181494
    13191495namespace detail {
     
    16151791template<>
    16161792BOOST_MPI_DECL void
    16171793communicator::send<packed_skeleton_oarchive>
    1618   (int dest, int tag, const packed_skeleton_oarchive& ar) const;
     1794                                   (int dest, int tag,
     1795                                    const packed_skeleton_oarchive& ar) const;
    16191796
    16201797/**
    16211798 * INTERNAL ONLY
     
    16241801BOOST_MPI_DECL void
    16251802communicator::send<content>(int dest, int tag, const content& c) const;
    16261803
     1804
     1805/**
     1806 * INTERNAL ONLY
     1807 */
     1808template<>
     1809BOOST_MPI_DECL void
     1810communicator::ssend<packed_oarchive>(int dest, int tag,
     1811                                    const packed_oarchive& ar) const;
     1812
     1813/**
     1814 * INTERNAL ONLY
     1815 */
     1816template<>
     1817BOOST_MPI_DECL void
     1818communicator::ssend<packed_skeleton_oarchive>
     1819                                   (int dest, int tag,
     1820                                    const packed_skeleton_oarchive& ar) const;
     1821
     1822/**
     1823 * INTERNAL ONLY
     1824 */
     1825template<>
     1826BOOST_MPI_DECL void
     1827communicator::ssend<content>(int dest, int tag, const content& c) const;
     1828
     1829
    16271830/**
    16281831 * INTERNAL ONLY
    16291832 */
     
    16641867 */
    16651868template<>
    16661869BOOST_MPI_DECL request
    1667 communicator::isend<packed_oarchive>(int dest, int tag,
    1668                                     const packed_oarchive& ar) const;
     1870communicator::isend<packed_oarchive>
     1871  (int dest, int tag, const packed_oarchive& ar) const;
    16691872
    16701873/**
    16711874 * INTERNAL ONLY
     
    16841887
    16851888/**
    16861889 * INTERNAL ONLY
     1890 */
     1891template<>
     1892BOOST_MPI_DECL request
     1893communicator::issend<packed_oarchive>
     1894  (int dest, int tag, const packed_oarchive& ar) const;
     1895
     1896/**
     1897 * INTERNAL ONLY
     1898 */
     1899template<>
     1900BOOST_MPI_DECL request
     1901communicator::issend<packed_skeleton_oarchive>
     1902  (int dest, int tag, const packed_skeleton_oarchive& ar) const;
     1903
     1904/**
     1905 * INTERNAL ONLY
     1906 */
     1907template<>
     1908BOOST_MPI_DECL request
     1909communicator::issend<content>(int dest, int tag, const content& c) const;
     1910
     1911/**
     1912 * INTERNAL ONLY
    16871913 */
    16881914template<>
    16891915BOOST_MPI_DECL request
  • boost/mpi/detail/communicator_sc.hpp

    diff -ruw -x '*~' -x '*.o' -x '*.a' boost_1_45_0.orig/boost/mpi/detail/communicator_sc.hpp boost_1_45_0/boost/mpi/detail/communicator_sc.hpp
    old new  
    1515
    1616template<typename T>
    1717void
    18 communicator::send(int dest, int tag, const skeleton_proxy<T>& proxy) const
     18communicator::send_impl(int dest, int tag, const skeleton_proxy<T>& proxy,
     19                        const bool synchronous) const
    1920{
    2021  packed_skeleton_oarchive ar(*this);
    2122  ar << proxy.object;
     23  if (synchronous)
     24    ssend(dest, tag, ar);
     25  else
    2226  send(dest, tag, ar);
    2327}
    2428
    2529template<typename T>
     30void
     31communicator::send(int dest, int tag, const skeleton_proxy<T>& proxy) const
     32{
     33  send_impl(dest, tag, proxy, false);
     34}
     35
     36template<typename T>
     37void
     38communicator::ssend(int dest, int tag, const skeleton_proxy<T>& proxy) const
     39{
     40  send_impl(dest, tag, proxy, true);
     41}
     42
     43template<typename T>
    2644status
    2745communicator::recv(int source, int tag, const skeleton_proxy<T>& proxy) const
    2846{
     
    4361
    4462template<typename T>
    4563request
    46 communicator::isend(int dest, int tag, const skeleton_proxy<T>& proxy) const
     64communicator::isend_impl(int dest, int tag, const skeleton_proxy<T>& proxy,
     65                         const bool synchronous) const
    4766{
    4867  shared_ptr<packed_skeleton_oarchive>
    4968    archive(new packed_skeleton_oarchive(*this));
    5069
    5170  *archive << proxy.object;
    52   request result = isend(dest, tag, *archive);
     71  request result = (synchronous?
     72                    issend(dest, tag, *archive)
     73                    : isend(dest, tag, *archive));
    5374  result.m_data = archive;
    5475  return result;
    5576}
    5677
     78template<typename T>
     79request
     80communicator::isend(int dest, int tag, const skeleton_proxy<T>& proxy) const
     81{
     82  return isend_impl(dest, tag, proxy, false);
     83}
     84
     85template<typename T>
     86request
     87communicator::issend(int dest, int tag, const skeleton_proxy<T>& proxy) const
     88{
     89  return isend_impl(dest, tag, proxy, true);
     90}
     91
    5792namespace detail {
    5893  template<typename T>
    5994  struct serialized_irecv_data<const skeleton_proxy<T> >
  • boost/mpi/detail/point_to_point.hpp

    diff -ruw -x '*~' -x '*.o' -x '*.a' boost_1_45_0.orig/boost/mpi/detail/point_to_point.hpp boost_1_45_0/boost/mpi/detail/point_to_point.hpp
    old new  
    1515
    1616namespace boost { namespace mpi { namespace detail {
    1717
    18 /** Sends a packed archive using MPI_Send. */
     18/** Sends a packed archive using MPI_Send/MPI_Ssend. */
    1919BOOST_MPI_DECL void
    2020packed_archive_send(MPI_Comm comm, int dest, int tag,
    21                     const packed_oarchive& ar);
     21                    const packed_oarchive& ar,
     22                    const bool synchronous = false);
    2223
    23 /** Sends a packed archive using MPI_Isend.
     24/** Sends a packed archive using MPI_Isend/MPI_Issend.
    2425 *
    2526 * This routine may split sends into multiple packets. The MPI_Request
    2627 * for each packet will be placed into the out_requests array, up to
     
    3233BOOST_MPI_DECL int
    3334packed_archive_isend(MPI_Comm comm, int dest, int tag,
    3435                     const packed_oarchive& ar,
    35                      MPI_Request* out_requests, int num_out_requests);
     36                     MPI_Request* out_requests, int num_out_requests,
     37                     const bool synchronous = false);
    3638
    3739/**
    3840 * \overload
     
    4042BOOST_MPI_DECL int
    4143packed_archive_isend(MPI_Comm comm, int dest, int tag,
    4244                     const packed_iarchive& ar,
    43                      MPI_Request* out_requests, int num_out_requests);
     45                     MPI_Request* out_requests, int num_out_requests,
     46                     const bool synchronous = false);
    4447
    4548/** Receives a packed archive using MPI_Recv. */
    4649BOOST_MPI_DECL void
  • libs/mpi/src/broadcast.cpp

    Only in boost_1_45_0: bootstrap.log
    diff -ruw -x '*~' -x '*.o' -x '*.a' boost_1_45_0.orig/libs/mpi/src/broadcast.cpp boost_1_45_0/libs/mpi/src/broadcast.cpp
    old new  
    3535    if (dest != root) {
    3636      // Build up send requests for each child send.
    3737      num_requests += detail::packed_archive_isend(comm, dest, tag, oa,
    38                                                    &requests[num_requests], 2);
     38                                                   &requests[num_requests], 2, false);
    3939    }
    4040  }
    4141
     
    7676        // Build up send requests for each child send.
    7777        num_requests += detail::packed_archive_isend(comm, dest, tag, ia,
    7878                                                     &requests[num_requests],
    79                                                      2);
     79                                                     2, false);
    8080      }
    8181    }
    8282
  • libs/mpi/src/communicator.cpp

    diff -ruw -x '*~' -x '*.o' -x '*.a' boost_1_45_0.orig/libs/mpi/src/communicator.cpp boost_1_45_0/libs/mpi/src/communicator.cpp
    old new  
    9494                          dest, tag, MPI_Comm(*this)));
    9595}
    9696
     97void communicator::ssend(int dest, int tag) const
     98{
     99  BOOST_MPI_CHECK_RESULT(MPI_Ssend,
     100                         (MPI_BOTTOM, 0, MPI_PACKED,
     101                          dest, tag, MPI_Comm(*this)));
     102}
     103
    97104status communicator::recv(int source, int tag) const
    98105{
    99106  status stat;
     
    192199communicator::send<packed_oarchive>(int dest, int tag,
    193200                                    const packed_oarchive& ar) const
    194201{
    195   detail::packed_archive_send(MPI_Comm(*this), dest, tag, ar);
     202  detail::packed_archive_send(MPI_Comm(*this), dest, tag, ar, false);
     203}
     204
     205template<>
     206void
     207communicator::ssend<packed_oarchive>(int dest, int tag,
     208                                    const packed_oarchive& ar) const
     209{
     210  detail::packed_archive_send(MPI_Comm(*this), dest, tag, ar, true);
     211}
     212
     213template<>
     214void
     215communicator::send<packed_skeleton_oarchive>(int dest, int tag,
     216                                             const packed_skeleton_oarchive& ar) const
     217{
     218  send(dest, tag, ar.get_skeleton());
    196219}
    197220
    198221template<>
    199222void
    200 communicator::send<packed_skeleton_oarchive>
    201   (int dest, int tag, const packed_skeleton_oarchive& ar) const
     223communicator::ssend<packed_skeleton_oarchive>(int dest, int tag,
     224                                              const packed_skeleton_oarchive& ar) const
    202225{
    203   this->send(dest, tag, ar.get_skeleton());
     226  ssend(dest, tag, ar.get_skeleton());
    204227}
    205228
    206229template<>
     
    212235}
    213236
    214237template<>
     238void communicator::ssend<content>(int dest, int tag, const content& c) const
     239{
     240  BOOST_MPI_CHECK_RESULT(MPI_Ssend,
     241                         (MPI_BOTTOM, 1, c.get_mpi_datatype(),
     242                          dest, tag, MPI_Comm(*this)));
     243}
     244
     245template<>
    215246status
    216247communicator::recv<packed_iarchive>(int source, int tag,
    217248                                    packed_iarchive& ar) const
     
    251282{
    252283  request req;
    253284  detail::packed_archive_isend(MPI_Comm(*this), dest, tag, ar,
    254                                &req.m_requests[0] ,2);
     285                               &req.m_requests[0], 2, false);
    255286  return req;
    256287}
    257288
    258289template<>
    259290request
    260 communicator::isend<packed_skeleton_oarchive>
    261   (int dest, int tag, const packed_skeleton_oarchive& ar) const
     291communicator::issend<packed_oarchive>(int dest, int tag,
     292                                     const packed_oarchive& ar) const
    262293{
    263   return this->isend(dest, tag, ar.get_skeleton());
     294  request req;
     295  detail::packed_archive_isend(MPI_Comm(*this), dest, tag, ar,
     296                               &req.m_requests[0], 2, true);
     297  return req;
     298}
     299
     300template<>
     301request
     302communicator::isend<packed_skeleton_oarchive>(int dest, int tag,
     303                                              const packed_skeleton_oarchive& ar) const
     304{
     305  return isend(dest, tag, ar.get_skeleton());
     306}
     307
     308template<>
     309request
     310communicator::issend<packed_skeleton_oarchive>(int dest, int tag,
     311                                               const packed_skeleton_oarchive& ar) const
     312{
     313  return issend(dest, tag, ar.get_skeleton());
    264314}
    265315
    266316template<>
     
    273323  return req;
    274324}
    275325
     326template<>
     327request communicator::issend<content>(int dest, int tag, const content& c) const
     328{
     329  request req;
     330  BOOST_MPI_CHECK_RESULT(MPI_Issend,
     331                         (MPI_BOTTOM, 1, c.get_mpi_datatype(),
     332                          dest, tag, MPI_Comm(*this), &req.m_requests[0]));
     333  return req;
     334}
     335   
    276336request communicator::isend(int dest, int tag) const
    277337{
    278338  request req;
     
    280340                         (MPI_BOTTOM, 0, MPI_PACKED,
    281341                          dest, tag, MPI_Comm(*this), &req.m_requests[0]));
    282342  return req;
     343}
     344
     345request communicator::issend(int dest, int tag) const
     346{
     347  request req;
     348  BOOST_MPI_CHECK_RESULT(MPI_Issend,
     349                         (MPI_BOTTOM, 0, MPI_PACKED,
     350                          dest, tag, MPI_Comm(*this), &req.m_requests[0]));
     351  return req;
    283352}
    284353
    285354template<>
  • libs/mpi/src/point_to_point.cpp

    diff -ruw -x '*~' -x '*.o' -x '*.a' boost_1_45_0.orig/libs/mpi/src/point_to_point.cpp boost_1_45_0/libs/mpi/src/point_to_point.cpp
    old new  
    2626
    2727void
    2828packed_archive_send(MPI_Comm comm, int dest, int tag,
    29                     const packed_oarchive& ar)
     29                    const packed_oarchive& ar,
     30                    const bool synchronous)
    3031{
    3132  const void* size = &ar.size();
     33  // size and content are sent in separate messages: since we only
     34  // need a guarantee that the *content* has arrived when a
     35  // synchronous call is done, we can send the content with MPI_Ssend
     36  // and use a "standard send" for the size.
    3237  BOOST_MPI_CHECK_RESULT(MPI_Send,
    3338                         (const_cast<void*>(size), 1,
    3439                          get_mpi_datatype<std::size_t>(ar.size()),
    3540                          dest, tag, comm));
     41  if (synchronous) {
     42    BOOST_MPI_CHECK_RESULT(MPI_Ssend,
     43                           (const_cast<void*>(ar.address()), ar.size(),
     44                            MPI_PACKED,
     45                            dest, tag, comm));
     46  } else {
    3647  BOOST_MPI_CHECK_RESULT(MPI_Send,
    3748                         (const_cast<void*>(ar.address()), ar.size(),
    3849                          MPI_PACKED,
    3950                          dest, tag, comm));
     51  };
    4052}
    4153
    4254int
    4355packed_archive_isend(MPI_Comm comm, int dest, int tag,
    4456                     const packed_oarchive& ar,
    45                      MPI_Request* out_requests, int num_out_requests)
     57                     MPI_Request* out_requests, int num_out_requests,
     58                     const bool synchronous)
    4659{
    4760  assert(num_out_requests >= 2);
    4861  const void* size = &ar.size();
     62  // size and content are sent in separate messages: since we only
     63  // need a guarantee that the *content* has arrived when a
     64  // synchronous call is done, we can send the content with MPI_Ssend
     65  // and use a "standard send" for the size.
    4966  BOOST_MPI_CHECK_RESULT(MPI_Isend,
    5067                         (const_cast<void*>(size), 1,
    5168                          get_mpi_datatype<std::size_t>(ar.size()),
    5269                          dest, tag, comm, out_requests));
     70  if (synchronous) {
     71    BOOST_MPI_CHECK_RESULT(MPI_Issend,
     72                           (const_cast<void*>(ar.address()), ar.size(),
     73                            MPI_PACKED,
     74                            dest, tag, comm, out_requests + 1));
     75  } else {
    5376  BOOST_MPI_CHECK_RESULT(MPI_Isend,
    5477                         (const_cast<void*>(ar.address()), ar.size(),
    5578                          MPI_PACKED,
    5679                          dest, tag, comm, out_requests + 1));
     80  };
    5781
    5882  return 2;
    5983}
     
    6185int
    6286packed_archive_isend(MPI_Comm comm, int dest, int tag,
    6387                     const packed_iarchive& ar,
    64                      MPI_Request* out_requests, int num_out_requests)
     88                     MPI_Request* out_requests, int num_out_requests,
     89                     const bool synchronous)
    6590{
    6691  assert(num_out_requests >= 2);
    6792
    6893  const void* size = &ar.size();
     94  // size and content are sent in separate messages: since we only
     95  // need a guarantee that the *content* has arrived when a
     96  // synchronous call is done, we can send the content with MPI_Ssend
     97  // and use a "standard send" for the size.
    6998  BOOST_MPI_CHECK_RESULT(MPI_Isend,
    7099                         (const_cast<void*>(size), 1,
    71100                          get_mpi_datatype<std::size_t>(ar.size()),
    72101                          dest, tag, comm, out_requests));
     102  if (synchronous) {
     103    BOOST_MPI_CHECK_RESULT(MPI_Issend,
     104                           (const_cast<void*>(ar.address()), ar.size(),
     105                            MPI_PACKED,
     106                            dest, tag, comm, out_requests + 1));
     107  } else {
    73108  BOOST_MPI_CHECK_RESULT(MPI_Isend,
    74109                         (const_cast<void*>(ar.address()), ar.size(),
    75110                          MPI_PACKED,
    76111                          dest, tag, comm, out_requests + 1));
     112  };
    77113
    78114  return 2;
    79115}
  • libs/mpi/test/nonblocking_test.cpp

    diff -ruw -x '*~' -x '*.o' -x '*.a' boost_1_45_0.orig/libs/mpi/test/nonblocking_test.cpp boost_1_45_0/libs/mpi/test/nonblocking_test.cpp
    old new  
    4141  "test_some (keep results)"
    4242};
    4343
     44enum synch_behavior { synch_no, synch_yes, synch_both };
     45
    4446
    4547template<typename T>
    4648void
    4749nonblocking_test(const communicator& comm, const T* values, int num_values,
    48                  const char* kind, method_kind method = mk_all)
     50                 const char* kind, method_kind method = mk_all,
     51                 synch_behavior synch = synch_both)
    4952{
    5053  using boost::mpi::wait_any;
    5154  using boost::mpi::test_any;
     
    5457  using boost::mpi::wait_some;
    5558  using boost::mpi::test_some;
    5659
     60  if (synch == synch_both) {
     61    nonblocking_test(comm, values, num_values, kind, method, synch_no);
     62    nonblocking_test(comm, values, num_values, kind, method, synch_yes);
     63    return;
     64  };
     65  const bool synchronous = (synch == synch_yes);
     66
    5767  if (method == mk_all || method == mk_all_except_test_all) {
    58     nonblocking_test(comm, values, num_values, kind, mk_wait_any);
    59     nonblocking_test(comm, values, num_values, kind, mk_test_any);
    60     nonblocking_test(comm, values, num_values, kind, mk_wait_all);
    61     nonblocking_test(comm, values, num_values, kind, mk_wait_all_keep);
     68    nonblocking_test(comm, values, num_values, kind, mk_wait_any, synch);
     69    nonblocking_test(comm, values, num_values, kind, mk_test_any, synch);
     70    nonblocking_test(comm, values, num_values, kind, mk_wait_all, synch);
     71    nonblocking_test(comm, values, num_values, kind, mk_wait_all_keep, synch);
    6272    if (method == mk_all) {
    63       nonblocking_test(comm, values, num_values, kind, mk_test_all);
    64       nonblocking_test(comm, values, num_values, kind, mk_test_all_keep);
     73      nonblocking_test(comm, values, num_values, kind, mk_test_all, synch);
     74      nonblocking_test(comm, values, num_values, kind, mk_test_all_keep, synch);
    6575    }
    66     nonblocking_test(comm, values, num_values, kind, mk_wait_some);
    67     nonblocking_test(comm, values, num_values, kind, mk_wait_some_keep);
    68     nonblocking_test(comm, values, num_values, kind, mk_test_some);
    69     nonblocking_test(comm, values, num_values, kind, mk_test_some_keep);
     76    nonblocking_test(comm, values, num_values, kind, mk_wait_some, synch);
     77    nonblocking_test(comm, values, num_values, kind, mk_wait_some_keep, synch);
     78    nonblocking_test(comm, values, num_values, kind, mk_test_some, synch);
     79    nonblocking_test(comm, values, num_values, kind, mk_test_some_keep, synch);
    7080  } else {
     81
    7182    if (comm.rank() == 0) {
    7283      std::cout << "Testing " << method_kind_names[method]
    73                 << " with " << kind << "...";
     84                << " with " << kind
     85                << (synchronous ? " (ssend) " : "")
     86                << "...";
    7487      std::cout.flush();
    7588    }
    7689
     
    8295
    8396    std::vector<request> reqs;
    8497    // Send/receive the first value
    85     reqs.push_back(comm.isend((comm.rank() + 1) % comm.size(), 0, values[0]));
    8698    reqs.push_back(comm.irecv((comm.rank() + comm.size() - 1) % comm.size(),
    8799                              0, incoming_value));
     100    if (synchronous)
     101      reqs.push_back(comm.issend((comm.rank() + 1) % comm.size(), 0, values[0]));
     102    else
     103      reqs.push_back(comm.isend((comm.rank() + 1) % comm.size(), 0, values[0]));
     104
    88105
    89106    if (method != mk_wait_any && method != mk_test_any) {
    90107#ifndef LAM_MPI
     
    94111      // when using shared memory, not TCP.
    95112
    96113      // Send/receive an empty message
     114      if (synchronous)
     115        reqs.push_back(comm.issend((comm.rank() + 1) % comm.size(), 1));
     116      else
    97117      reqs.push_back(comm.isend((comm.rank() + 1) % comm.size(), 1));
    98118      reqs.push_back(comm.irecv((comm.rank() + comm.size() - 1) % comm.size(),
    99119                                1));
    100120#endif
    101121
    102122      // Send/receive an array
     123      if (synchronous)
     124        reqs.push_back(comm.issend((comm.rank() + 1) % comm.size(), 2, values,
     125                                  num_values));
     126      else
    103127      reqs.push_back(comm.isend((comm.rank() + 1) % comm.size(), 2, values,
    104128                                num_values));
    105129      reqs.push_back(comm.irecv((comm.rank() + comm.size() - 1) % comm.size(),
     
    121145          result = test_any(reqs.begin(), reqs.end());
    122146        } while (!result);
    123147        if (result->second == reqs.begin())
    124           reqs[1].wait();
     148          reqs[1].wait(); // wait for the isend()
    125149        else
    126           reqs[0].wait();
    127         break;
     150          reqs[0].wait(); // wait for the irecv()
    128151      }
     152      break;
    129153
    130154    case mk_wait_all:
    131155      wait_all(reqs.begin(), reqs.end());
  • libs/mpi/test/skeleton_content_test.cpp

    diff -ruw -x '*~' -x '*.o' -x '*.a' boost_1_45_0.orig/libs/mpi/test/skeleton_content_test.cpp boost_1_45_0/libs/mpi/test/skeleton_content_test.cpp
    old new  
    2323
    2424void
    2525test_skeleton_and_content(const communicator& comm, int root,
    26                           bool manual_broadcast)
     26                          bool manual_broadcast, bool synchronous)
    2727{
    2828  using boost::mpi::skeleton;
    2929  using boost::mpi::content;
     
    4141      original_list.push_back(i);
    4242
    4343    std::cout << "Broadcasting integer list skeleton from root " << root
     44              << (synchronous and manual_broadcast? " (ssend) " : "")
    4445              << "...";
    4546    if (manual_broadcast) {
    4647      // Broadcast the skeleton (manually)
    4748      for (int p = 0; p < comm.size(); ++p)
    48         if (p != root) comm.send(p, 0, skeleton(original_list));
     49        if (p != root) {
     50          if (synchronous)
     51            comm.ssend(p, 0, skeleton(original_list));
     52          else
     53            comm.send(p, 0, skeleton(original_list));
     54        };
    4955    } else {
    5056      broadcast(comm, skeleton(original_list), root);
    5157    }
     
    5359
    5460    // Broadcast the content (manually)
    5561    std::cout << "Broadcasting integer list content from root " << root
    56               << "...";
     62              << (synchronous? " (ssend) " : "") << "...";
    5763    {
    5864      content c = get_content(original_list);
    5965      for (int p = 0; p < comm.size(); ++p)
    60         if (p != root) comm.send(p, 1, c);
     66        if (p != root) {
     67          if (synchronous)
     68            comm.ssend(p, 1, c);
     69          else
     70            comm.send(p, 1, c);
     71        };
    6172    }
    6273    std::cout << "OK." << std::endl;
    6374
    6475    // Reverse the list, broadcast the content again
    6576    std::reverse(original_list.begin(), original_list.end());
    6677    std::cout << "Broadcasting reversed integer list content from root "
    67               << root << "...";
     78              << root << (synchronous? " (ssend) " : "") << "...";
    6879    {
    6980      content c = get_content(original_list);
    7081      for (int p = 0; p < comm.size(); ++p)
    71         if (p != root) comm.send(p, 2, c);
     82        if (p != root) {
     83          if (synchronous)
     84            comm.ssend(p, 2, c);
     85          else
     86            comm.send(p, 2, c);
     87        };
    7288    }
    7389    std::cout << "OK." << std::endl;
    7490  } else {
     
    101117  (comm.barrier)();
    102118}
    103119
     120
    104121void
    105 test_skeleton_and_content_nonblocking(const communicator& comm, int root)
     122test_skeleton_and_content_nonblocking(const communicator& comm, int root,
     123                                      bool synchronous)
    106124{
    107125  using boost::mpi::skeleton;
    108126  using boost::mpi::content;
     
    122140      original_list.push_back(i);
    123141
    124142    std::cout << "Non-blocking broadcast of integer list skeleton from root " << root
     143              << (synchronous? " (ssend) " : "")
    125144              << "...";
    126145
    127146    // Broadcast the skeleton (manually)
    128147    {
    129148      std::vector<request> reqs;
    130149      for (int p = 0; p < comm.size(); ++p)
    131         if (p != root)
     150        if (p != root) {
     151          if (synchronous)
     152            reqs.push_back(comm.issend(p, 0, skeleton(original_list)));
     153          else
    132154          reqs.push_back(comm.isend(p, 0, skeleton(original_list)));
     155        };
    133156      wait_all(reqs.begin(), reqs.end());
    134157    }
    135158    std::cout << "OK." << std::endl;
    136159
    137160    // Broadcast the content (manually)
    138161    std::cout << "Non-blocking broadcast of integer list content from root " << root
     162              << (synchronous? " (ssend) " : "")
    139163              << "...";
    140164    {
    141165      content c = get_content(original_list);
    142166      std::vector<request> reqs;
    143167      for (int p = 0; p < comm.size(); ++p)
    144         if (p != root) reqs.push_back(comm.isend(p, 1, c));
     168        if (p != root) {
     169          if (synchronous)
     170            reqs.push_back(comm.issend(p, 1, c));
     171          else
     172            reqs.push_back(comm.isend(p, 1, c));
     173        };
    145174      wait_all(reqs.begin(), reqs.end());
    146175    }
    147176    std::cout << "OK." << std::endl;
     
    149178    // Reverse the list, broadcast the content again
    150179    std::reverse(original_list.begin(), original_list.end());
    151180    std::cout << "Non-blocking broadcast of reversed integer list content from root "
     181              << (synchronous? " (ssend) " : "")
    152182              << root << "...";
    153183    {
    154184      std::vector<request> reqs;
    155185      content c = get_content(original_list);
    156186      for (int p = 0; p < comm.size(); ++p)
    157         if (p != root) reqs.push_back(comm.isend(p, 2, c));
     187        if (p != root) {
     188          if (synchronous)
     189            reqs.push_back(comm.issend(p, 2, c));
     190          else
     191            reqs.push_back(comm.isend(p, 2, c));
     192        };
    158193      wait_all(reqs.begin(), reqs.end());
    159194    }
    160195    std::cout << "OK." << std::endl;
     
    199234    MPI_Abort(comm, -1);
    200235  }
    201236
    202   test_skeleton_and_content(comm, 0, true);
    203   test_skeleton_and_content(comm, 0, false);
    204   test_skeleton_and_content(comm, 1, true);
    205   test_skeleton_and_content(comm, 1, false);
    206   test_skeleton_and_content_nonblocking(comm, 0);
    207   test_skeleton_and_content_nonblocking(comm, 1);
     237  // non-synchronous
     238  test_skeleton_and_content(comm, 0, true, false);
     239  test_skeleton_and_content(comm, 0, false, false);
     240  test_skeleton_and_content(comm, 1, true, false);
     241  test_skeleton_and_content(comm, 1, false, false);
     242  // synchronous
     243  test_skeleton_and_content(comm, 0, true, true);
     244  test_skeleton_and_content(comm, 0, false, true);
     245  test_skeleton_and_content(comm, 1, true, true);
     246  test_skeleton_and_content(comm, 1, false, true);
     247
     248  test_skeleton_and_content_nonblocking(comm, 0, false);
     249  test_skeleton_and_content_nonblocking(comm, 1, false);
     250  test_skeleton_and_content_nonblocking(comm, 0, true);
     251  test_skeleton_and_content_nonblocking(comm, 1, true);
    208252
    209253  return 0;
    210254}