Boost logo

Boost-Commit :

From: troyer_at_[hidden]
Date: 2008-01-10 04:49:19


Author: troyer
Date: 2008-01-10 04:49:16 EST (Thu, 10 Jan 2008)
New Revision: 42647
URL: http://svn.boost.org/trac/boost/changeset/42647

Log:
Optimizations for Boost.MPI
Added:
   trunk/boost/mpi/detail/binary_buffer_iprimitive.hpp (contents, props changed)
   trunk/boost/mpi/detail/binary_buffer_oprimitive.hpp (contents, props changed)
Text files modified:
   trunk/boost/mpi/config.hpp | 5 ++++
   trunk/boost/mpi/datatype.hpp | 32 ++++++++++++++++++++++++----
   trunk/boost/mpi/datatype_fwd.hpp | 2 +
   trunk/boost/mpi/detail/packed_iprimitive.hpp | 15 ++++++-------
   trunk/boost/mpi/packed_iarchive.hpp | 45 +++++++++++++++++++++++++++++++++++----
   trunk/boost/mpi/packed_oarchive.hpp | 36 +++++++++++++++++++++++++++++--
   trunk/boost/mpi/status.hpp | 2 +
   7 files changed, 116 insertions(+), 21 deletions(-)

Modified: trunk/boost/mpi/config.hpp
==============================================================================
--- trunk/boost/mpi/config.hpp (original)
+++ trunk/boost/mpi/config.hpp 2008-01-10 04:49:16 EST (Thu, 10 Jan 2008)
@@ -20,6 +20,11 @@
 #include <mpi.h>
 #include <boost/config.hpp>
 
+/** @brief Define this macro to avoid expensice MPI_Pack/Unpack calls on
+ * homogeneous machines.
+*/
+//#define BOOST_MPI_HOMOGENEOUS
+
 // If this is an MPI-2 implementation, define configuration macros for
 // the features we are interested in.
 #if defined(MPI_VERSION) && MPI_VERSION == 2

Modified: trunk/boost/mpi/datatype.hpp
==============================================================================
--- trunk/boost/mpi/datatype.hpp (original)
+++ trunk/boost/mpi/datatype.hpp 2008-01-10 04:49:16 EST (Thu, 10 Jan 2008)
@@ -23,6 +23,7 @@
 #include <boost/config.hpp>
 #include <boost/mpl/bool.hpp>
 #include <boost/mpl/or.hpp>
+#include <boost/mpl/and.hpp>
 #include <boost/mpi/detail/mpi_datatype_cache.hpp>
 #include <boost/mpl/assert.hpp>
 #include <utility> // for std::pair
@@ -199,6 +200,9 @@
 {}
 
 /// INTERNAL ONLY
+BOOST_MPI_DATATYPE(packed, MPI_PACKED, builtin);
+
+/// INTERNAL ONLY
 BOOST_MPI_DATATYPE(char, MPI_CHAR, builtin);
 
 /// INTERNAL ONLY
@@ -252,6 +256,14 @@
 BOOST_MPI_DATATYPE(std::pair<BOOST_MPI_LIST2(int, int>), MPI_2INT, builtin);
 #undef BOOST_MPI_LIST2
 
+/// specialization of is_mpi_datatype for pairs
+template <class T, class U>
+struct is_mpi_datatype<std::pair<T,U> >
+ : public mpl::and_<is_mpi_datatype<T>,is_mpi_datatype<U> >
+{
+};
+
+
 #if 0
 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
 BOOST_MPI_DATATYPE(wchar_t, MPI_WCHAR, builtin);
@@ -265,6 +277,11 @@
 
 #endif // Doxygen
 
+#if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)
+BOOST_MPI_DATATYPE(__int64, MPI_LONG_LONG_INT, builtin);
+BOOST_MPI_DATATYPE(unsigned __int64, MPI_UNSIGNED_LONG_LONG, builtin);
+#endif
+
 namespace detail {
   inline MPI_Datatype build_mpi_datatype_for_bool()
   {
@@ -290,11 +307,16 @@
   : boost::mpl::bool_<true>
 {};
 
-/// INTERNAL ONLY
-template<typename T, typename U>
-struct is_mpi_datatype<std::pair<T, U> >
- : mpl::and_<is_mpi_datatype<T>, is_mpi_datatype<U> > { };
-
 } } // end namespace boost::mpi
 
+// define a macro to make explicit designation of this more transparent
+#define BOOST_IS_MPI_DATATYPE(T) \
+namespace boost { \
+namespace mpi { \
+template<> \
+struct is_mpi_datatype< T > : mpl::true_ {}; \
+}} \
+/**/
+
+
 #endif // BOOST_MPI_MPI_DATATYPE_HPP

Modified: trunk/boost/mpi/datatype_fwd.hpp
==============================================================================
--- trunk/boost/mpi/datatype_fwd.hpp (original)
+++ trunk/boost/mpi/datatype_fwd.hpp 2008-01-10 04:49:16 EST (Thu, 10 Jan 2008)
@@ -27,6 +27,8 @@
 template<typename T> struct is_mpi_datatype;
 template<typename T> MPI_Datatype get_mpi_datatype(const T& x = T());
 
+/// a dummy data type giving MPI_PACKED as its MPI_Datatype
+struct packed {};
 } } // end namespace boost::mpi
 
 #endif // BOOST_MPI_MPI_DATATYPE_FWD_HPP

Added: trunk/boost/mpi/detail/binary_buffer_iprimitive.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/mpi/detail/binary_buffer_iprimitive.hpp 2008-01-10 04:49:16 EST (Thu, 10 Jan 2008)
@@ -0,0 +1,121 @@
+// (C) Copyright 2005-2007 Matthias Troyer
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Matthias Troyer
+
+#ifndef BOOST_MPI_BINARY_BUFFER_IPRIMITIVE_HPP
+#define BOOST_MPI_BINARY_BUFFER_IPRIMITIVE_HPP
+
+#include <mpi.h>
+#include <iostream>
+#include <cstddef> // size_t
+#include <boost/config.hpp>
+#include <boost/mpi/exception.hpp>
+#include <boost/assert.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/serialization/array.hpp>
+#include <boost/serialization/is_bitwise_serializable.hpp>
+#include <vector>
+#include <boost/mpi/allocator.hpp>
+
+namespace boost { namespace mpi {
+
+/// deserialization using MPI_Unpack
+
+class BOOST_MPI_DECL binary_buffer_iprimitive
+{
+public:
+ /// the type of the buffer from which the data is unpacked upon deserialization
+ typedef std::vector<char, allocator<char> > buffer_type;
+
+ binary_buffer_iprimitive(buffer_type & b, MPI_Comm const &, int position = 0)
+ : buffer_(b),
+ position(position)
+ {
+ }
+
+ void* address ()
+ {
+ return &buffer_.front();
+ }
+
+ void const* address () const
+ {
+ return &buffer_.front();
+ }
+
+ const std::size_t& size() const
+ {
+ return size_ = buffer_.size();
+ }
+
+ void resize(std::size_t s)
+ {
+ buffer_.resize(s);
+ }
+
+ void load_binary(void *address, std::size_t count)
+ {
+ load_impl(address,count);
+ }
+
+ // fast saving of arrays of fundamental types
+ template<class T>
+ void load_array(serialization::array<T> const& x, unsigned int /* file_version */)
+ {
+ BOOST_MPL_ASSERT((serialization::is_bitwise_serializable<BOOST_DEDUCED_TYPENAME remove_const<T>::type>));
+ if (x.count())
+ load_impl(x.address(), sizeof(T)*x.count());
+ }
+
+ typedef serialization::is_bitwise_serializable<mpl::_1> use_array_optimization;
+
+ template<class T>
+ void load(serialization::array<T> const& x)
+ {
+ load_array(x,0u);
+ }
+
+ // default saving of primitives.
+ template<class T>
+ void load( T & t)
+ {
+ BOOST_MPL_ASSERT((serialization::is_bitwise_serializable<BOOST_DEDUCED_TYPENAME remove_const<T>::type>));
+ load_impl(&t, sizeof(T));
+ }
+
+ void load( std::string & s)
+ {
+ unsigned int l;
+ load(l);
+ // borland de-allocator fixup
+ #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
+ if(NULL != s.data())
+ #endif
+ s.resize(l);
+ // note breaking a rule here - could be a problem on some platform
+ load_impl(const_cast<char *>(s.data()),l);
+ }
+
+private:
+
+ void load_impl(void * p, int l)
+ {
+ if (position+l > static_cast<int>(buffer_.size()))
+ std::cerr << position << " " << l << " " << buffer_.size() << "\n";
+ assert(position+l<=static_cast<int>(buffer_.size()));
+ std::memcpy(p,&buffer_[position],l);
+ position += l;
+ }
+
+ buffer_type & buffer_;
+ mutable std::size_t size_;
+ int position;
+};
+
+} } // end namespace boost::mpi
+
+#endif // BOOST_MPI_PACKED_IPRIMITIVE_HPP

Added: trunk/boost/mpi/detail/binary_buffer_oprimitive.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/mpi/detail/binary_buffer_oprimitive.hpp 2008-01-10 04:49:16 EST (Thu, 10 Jan 2008)
@@ -0,0 +1,103 @@
+// (C) Copyright 2005-2007 Matthias Troyer
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Matthias Troyer
+
+#ifndef BOOST_MPI_BINARY_BUFFER_OPRIMITIVE_HPP
+#define BOOST_MPI_BINARY_BUFFER_OPRIMITIVE_HPP
+
+#include <mpi.h>
+#include <iostream>
+#include <cstddef> // size_t
+#include <boost/config.hpp>
+
+#include <boost/serialization/array.hpp>
+#include <boost/serialization/is_bitwise_serializable.hpp>
+#include <boost/assert.hpp>
+#include <boost/mpl/assert.hpp>
+#include <vector>
+#include <boost/mpi/allocator.hpp>
+#include <boost/mpl/always.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+namespace boost { namespace mpi {
+
+/// serialization using binary copy into a buffer
+
+class BOOST_MPI_DECL binary_buffer_oprimitive
+{
+public:
+ /// the type of the buffer into which the data is packed upon serialization
+ typedef std::vector<char, allocator<char> > buffer_type;
+
+ binary_buffer_oprimitive(buffer_type & b, MPI_Comm const &)
+ : buffer_(b)
+ {
+ }
+
+ void const * address() const
+ {
+ return &buffer_.front();
+ }
+
+ const std::size_t& size() const
+ {
+ return size_ = buffer_.size();
+ }
+
+ void save_binary(void const *address, std::size_t count)
+ {
+ save_impl(address,count);
+ }
+
+ // fast saving of arrays
+ template<class T>
+ void save_array(serialization::array<T> const& x, unsigned int /* file_version */)
+ {
+
+ BOOST_MPL_ASSERT((serialization::is_bitwise_serializable<BOOST_DEDUCED_TYPENAME remove_const<T>::type>));
+ if (x.count())
+ save_impl(x.address(), x.count()*sizeof(T));
+ }
+
+ template<class T>
+ void save(serialization::array<T> const& x)
+ {
+ save_array(x,0u);
+ }
+
+ typedef serialization::is_bitwise_serializable<mpl::_1> use_array_optimization;
+
+ // default saving of primitives.
+ template<class T>
+ void save(const T & t)
+ {
+ BOOST_MPL_ASSERT((serialization::is_bitwise_serializable<BOOST_DEDUCED_TYPENAME remove_const<T>::type>));
+ save_impl(&t, sizeof(T));
+ }
+
+ void save(const std::string &s)
+ {
+ unsigned int l = static_cast<unsigned int>(s.size());
+ save(l);
+ save_impl(s.data(),s.size());
+ }
+
+private:
+
+ void save_impl(void const * p, int l)
+ {
+ char const* ptr = reinterpret_cast<char const*>(p);
+ buffer_.insert(buffer_.end(),ptr,ptr+l);
+ }
+
+ buffer_type& buffer_;
+ mutable std::size_t size_;
+};
+
+} } // end namespace boost::mpi
+
+#endif // BOOST_MPI_BINARY_BUFFER_OPRIMITIVE_HPP

Modified: trunk/boost/mpi/detail/packed_iprimitive.hpp
==============================================================================
--- trunk/boost/mpi/detail/packed_iprimitive.hpp (original)
+++ trunk/boost/mpi/detail/packed_iprimitive.hpp 2008-01-10 04:49:16 EST (Thu, 10 Jan 2008)
@@ -65,20 +65,19 @@
 
     // fast saving of arrays of fundamental types
     template<class T>
- void load_array(serialization::array<T> & x, unsigned int /* file_version */)
+ void load_array(serialization::array<T> const& x, unsigned int /* file_version */)
     {
       if (x.count())
         load_impl(x.address(), get_mpi_datatype(*x.address()), x.count());
     }
 
- typedef is_mpi_datatype<mpl::_1> use_array_optimization;
+ template<class T>
+ void load(serialization::array<T> const& x)
+ {
+ load_array(x,0u);
+ }
 
-#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
- friend class archive::load_access;
-protected:
-#else
-public:
-#endif
+ typedef is_mpi_datatype<mpl::_1> use_array_optimization;
 
     // default saving of primitives.
     template<class T>

Modified: trunk/boost/mpi/packed_iarchive.hpp
==============================================================================
--- trunk/boost/mpi/packed_iarchive.hpp (original)
+++ trunk/boost/mpi/packed_iarchive.hpp 2008-01-10 04:49:16 EST (Thu, 10 Jan 2008)
@@ -23,10 +23,17 @@
 #include <boost/archive/basic_binary_iarchive.hpp>
 #include <boost/archive/shared_ptr_helper.hpp>
 #include <boost/mpi/detail/packed_iprimitive.hpp>
+#include <boost/mpi/detail/binary_buffer_iprimitive.hpp>
 #include <boost/assert.hpp>
 
 namespace boost { namespace mpi {
 
+#ifdef BOOST_MPI_HOMOGENEOUS
+ typedef binary_buffer_iprimitive iprimitive;
+#else
+ typedef packed_iprimitive iprimitive;
+#endif
+
 /** @brief An archive that packs binary data into an MPI buffer.
  *
  * The @c packed_iarchive class is an Archiver (as in the
@@ -36,7 +43,7 @@
  * implementation to perform serialization.
  */
 class BOOST_MPI_DECL packed_iarchive
- : public packed_iprimitive
+ : public iprimitive
   , public archive::basic_binary_iarchive<packed_iarchive>
   , public archive::detail::shared_ptr_helper
 {
@@ -59,7 +66,7 @@
    * deserialization will begin.
    */
   packed_iarchive(MPI_Comm const & comm, buffer_type & b, unsigned int flags = boost::archive::no_header, int position = 0)
- : packed_iprimitive(b,comm,position),
+ : iprimitive(b,comm,position),
           archive::basic_binary_iarchive<packed_iarchive>(flags)
         {}
 
@@ -70,16 +77,44 @@
    * @param comm The communicator over which this archive will be
    * sent.
    *
+ * @param s The size of the buffer to be received.
+ *
    * @param flags Control the serialization of the data types. Refer
    * to the Boost.Serialization documentation before changing the
    * default flags.
    */
   packed_iarchive
- ( MPI_Comm const & comm , unsigned int flags = boost::archive::no_header)
- : packed_iprimitive(internal_buffer_,comm),
- archive::basic_binary_iarchive<packed_iarchive>(flags)
+ ( MPI_Comm const & comm , std::size_t s=0,
+ unsigned int flags = boost::archive::no_header)
+ : iprimitive(internal_buffer_,comm)
+ , archive::basic_binary_iarchive<packed_iarchive>(flags)
+ , internal_buffer_(s)
         {}
 
+ // Load everything else in the usual way, forwarding on to the Base class
+ template<class T>
+ void load_override(T& x, int version, mpl::false_)
+ {
+ archive::basic_binary_iarchive<packed_iarchive>::load_override(x,version);
+ }
+
+ // Load it directly using the primnivites
+ template<class T>
+ void load_override(T& x, int version, mpl::true_)
+ {
+ iprimitive::load(x);
+ }
+
+ // Load all supported datatypes directly
+ template<class T>
+ void load_override(T& x, int version)
+ {
+ typedef typename mpl::apply1<use_array_optimization
+ , BOOST_DEDUCED_TYPENAME remove_const<T>::type
+ >::type use_optimized;
+ load_override(x, version, use_optimized());
+ }
+
 private:
   /// An internal buffer to be used when the user does not supply his
   /// own buffer.

Modified: trunk/boost/mpi/packed_oarchive.hpp
==============================================================================
--- trunk/boost/mpi/packed_oarchive.hpp (original)
+++ trunk/boost/mpi/packed_oarchive.hpp 2008-01-10 04:49:16 EST (Thu, 10 Jan 2008)
@@ -22,9 +22,16 @@
 #include <boost/archive/detail/auto_link_archive.hpp>
 #include <boost/archive/basic_binary_oarchive.hpp>
 #include <boost/mpi/detail/packed_oprimitive.hpp>
+#include <boost/mpi/detail/binary_buffer_oprimitive.hpp>
 
 namespace boost { namespace mpi {
 
+#ifdef BOOST_MPI_HOMOGENEOUS
+ typedef binary_buffer_oprimitive oprimitive;
+#else
+ typedef packed_oprimitive oprimitive;
+#endif
+
 /** @brief An archive that unpacks binary data from an MPI buffer.
  *
  * The @c packed_oarchive class is an Archiver (as in the
@@ -33,8 +40,9 @@
  * type and will use the @c MPI_Unpack function of the underlying MPI
  * implementation to perform deserialization.
  */
+
 class BOOST_MPI_DECL packed_oarchive
- : public packed_oprimitive,
+ : public oprimitive,
     public archive::basic_binary_oarchive<packed_oarchive>
 {
 public:
@@ -53,7 +61,7 @@
    * default flags.
    */
   packed_oarchive( MPI_Comm const & comm, buffer_type & b, unsigned int flags = boost::archive::no_header)
- : packed_oprimitive(b,comm),
+ : oprimitive(b,comm),
            archive::basic_binary_oarchive<packed_oarchive>(flags)
         {}
 
@@ -69,10 +77,31 @@
    * default flags.
    */
   packed_oarchive ( MPI_Comm const & comm, unsigned int flags = boost::archive::no_header)
- : packed_oprimitive(internal_buffer_,comm),
+ : oprimitive(internal_buffer_,comm),
            archive::basic_binary_oarchive<packed_oarchive>(flags)
         {}
 
+ // Save everything else in the usual way, forwarding on to the Base class
+ template<class T>
+ void save_override(T const& x, int version, mpl::false_)
+ {
+ archive::basic_binary_oarchive<packed_oarchive>::save_override(x,version);
+ }
+
+ // Save it directly using the primnivites
+ template<class T>
+ void save_override(T const& x, int version, mpl::true_)
+ {
+ oprimitive::save(x);
+ }
+
+ // Save all supported datatypes directly
+ template<class T>
+ void save_override(T const& x, int version)
+ {
+ typedef typename mpl::apply1<use_array_optimization,T>::type use_optimized;
+ save_override(x, version, use_optimized());
+ }
 
 private:
   /// An internal buffer to be used when the user does not supply his
@@ -86,4 +115,5 @@
 BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::mpi::packed_oarchive)
 
 
+
 #endif // BOOST_MPI_PACKED_OARCHIVE_HPP

Modified: trunk/boost/mpi/status.hpp
==============================================================================
--- trunk/boost/mpi/status.hpp (original)
+++ trunk/boost/mpi/status.hpp 2008-01-10 04:49:16 EST (Thu, 10 Jan 2008)
@@ -34,6 +34,8 @@
 {
  public:
   status() : m_count(-1) { }
+
+ status(MPI_Status const& s) : m_status(s), m_count(-1) {}
 
   /**
    * Retrieve the source of the message.


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk