Boost logo

Boost-Commit :

From: troyer_at_[hidden]
Date: 2007-11-14 02:00:03


Author: troyer
Date: 2007-11-14 02:00:02 EST (Wed, 14 Nov 2007)
New Revision: 41077
URL: http://svn.boost.org/trac/boost/changeset/41077

Log:
Added support for std::complex to serialization
Added:
   trunk/boost/serialization/complex.hpp (contents, props changed)
   trunk/boost/serialization/is_bitwise_serializable.hpp (contents, props changed)
   trunk/libs/serialization/test/test_complex.cpp (contents, props changed)
Text files modified:
   trunk/boost/archive/basic_binary_iprimitive.hpp | 11 +++++--
   trunk/boost/archive/basic_binary_oprimitive.hpp | 12 +++++++-
   trunk/boost/serialization/utility.hpp | 12 ++++++++
   trunk/libs/mpi/doc/mpi.qbk | 57 ++++++++++++++++++++++++++++++++++++++++
   trunk/libs/serialization/doc/traits.html | 26 ++++++++++++++++++
   trunk/libs/serialization/test/Jamfile.v2 | 1
   6 files changed, 114 insertions(+), 5 deletions(-)

Modified: trunk/boost/archive/basic_binary_iprimitive.hpp
==============================================================================
--- trunk/boost/archive/basic_binary_iprimitive.hpp (original)
+++ trunk/boost/archive/basic_binary_iprimitive.hpp 2007-11-14 02:00:02 EST (Wed, 14 Nov 2007)
@@ -49,7 +49,7 @@
 #include <boost/archive/archive_exception.hpp>
 #include <boost/archive/detail/auto_link_archive.hpp>
 #include <boost/mpl/placeholders.hpp>
-#include <boost/type_traits/is_fundamental.hpp>
+#include <boost/serialization/is_bitwise_serializable.hpp>
 #include <boost/serialization/array.hpp>
 #include <boost/archive/detail/abi_prefix.hpp> // must be the last header
 
@@ -113,7 +113,12 @@
     ~basic_binary_iprimitive();
 public:
     // we provide an optimized load for all fundamental types
- typedef is_fundamental<mpl::_1> use_array_optimization;
+ //typedef serialization::is_bitwise_serializable<mpl::_1>
+ // use_array_optimization;
+ struct use_array_optimization {
+ template <class T>
+ struct apply : public serialization::is_bitwise_serializable<T> {};
+ };
 
     // the optimized load_array dispatches to load_binary
     template <class ValueType>
@@ -160,7 +165,7 @@
         static_cast<Elem *>(address),
         s
     );
- if(scount != static_cast<std::size_t>(s))
+ if(scount != static_cast<std::streamsize>(s))
         boost::throw_exception(
             archive_exception(archive_exception::stream_error)
         );

Modified: trunk/boost/archive/basic_binary_oprimitive.hpp
==============================================================================
--- trunk/boost/archive/basic_binary_oprimitive.hpp (original)
+++ trunk/boost/archive/basic_binary_oprimitive.hpp 2007-11-14 02:00:02 EST (Wed, 14 Nov 2007)
@@ -46,7 +46,7 @@
 #include <boost/archive/basic_streambuf_locale_saver.hpp>
 #include <boost/archive/archive_exception.hpp>
 #include <boost/archive/detail/auto_link_archive.hpp>
-#include <boost/type_traits/is_fundamental.hpp>
+#include <boost/serialization/is_bitwise_serializable.hpp>
 #include <boost/mpl/placeholders.hpp>
 #include <boost/serialization/array.hpp>
 #include <boost/archive/detail/abi_prefix.hpp> // must be the last header
@@ -113,8 +113,16 @@
     BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
     ~basic_binary_oprimitive();
 public:
+
     // we provide an optimized save for all fundamental types
- typedef is_fundamental<mpl::_1> use_array_optimization;
+ // typedef serialization::is_bitwise_serializable<mpl::_1>
+ // use_array_optimization;
+ // workaround without using mpl lambdas
+ struct use_array_optimization {
+ template <class T>
+ struct apply : public serialization::is_bitwise_serializable<T> {};
+ };
+
 
     // the optimized save_array dispatches to save_binary
     template <class ValueType>

Added: trunk/boost/serialization/complex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/serialization/complex.hpp 2007-11-14 02:00:02 EST (Wed, 14 Nov 2007)
@@ -0,0 +1,56 @@
+#ifndef BOOST_SERIALIZATION_COMPLEX_HPP
+#define BOOST_SERIALIZATION_COMPLEX_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// serialization/utility.hpp:
+// serialization for stl utility templates
+
+// (C) Copyright 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)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#include <complex>
+#include <boost/config.hpp>
+
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/is_bitwise_serializable.hpp>
+
+namespace boost {
+namespace serialization {
+
+template<class Archive, class T>
+inline void serialize(
+ Archive & ar,
+ std::complex<T> & x,
+ const unsigned int /* file_version */
+){
+ ar & boost::serialization::make_nvp("real", x.real());
+ ar & boost::serialization::make_nvp("imag", x.imag());
+}
+
+/// specialization of serialization traits for complex
+template <class T>
+struct is_bitwise_serializable<std::complex<T> >
+ : public is_bitwise_serializable<T> {};
+
+template <class T>
+struct implementation_level<std::complex<T> >
+ : mpl::int_<object_serializable> {} ;
+
+// treat complex just like builtin arithmetic types for tracking
+template <class T>
+struct tracking_level<std::complex<T> >
+ : mpl::int_<track_never> {} ;
+
+} // serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_COMPLEX_HPP

Added: trunk/boost/serialization/is_bitwise_serializable.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/serialization/is_bitwise_serializable.hpp 2007-11-14 02:00:02 EST (Wed, 14 Nov 2007)
@@ -0,0 +1,46 @@
+// (C) Copyright 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
+
+/** @file is_bitwise_serializable.hpp
+ *
+ * This header provides a traits class for determining whether a class
+ * can be serialized (in a non-portable way) just by copying the bits.
+ */
+
+
+#ifndef BOOST_SERIALIZATION_IS_BITWISE_SERIALIZABLE_HPP
+#define BOOST_SERIALIZATION_IS_BITWISE_SERIALIZABLE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/bool.hpp>
+#include <boost/type_traits/is_arithmetic.hpp>
+
+namespace boost {
+namespace serialization {
+ template<class T>
+ struct is_bitwise_serializable
+ : public is_arithmetic<T>
+ {};
+} // namespace serialization
+} // namespace boost
+
+
+// define a macro to make explicit designation of this more transparent
+#define BOOST_IS_BITWISE_SERIALIZABLE(T) \
+namespace boost { \
+namespace serialization { \
+template<> \
+struct is_bitwise_serializable< T > : mpl::true_ {}; \
+}} \
+/**/
+
+#endif //BOOST_SERIALIZATION_IS_BITWISE_SERIALIZABLE_HPP

Modified: trunk/boost/serialization/utility.hpp
==============================================================================
--- trunk/boost/serialization/utility.hpp (original)
+++ trunk/boost/serialization/utility.hpp 2007-11-14 02:00:02 EST (Wed, 14 Nov 2007)
@@ -22,6 +22,7 @@
 
 #include <boost/type_traits/remove_const.hpp>
 #include <boost/serialization/nvp.hpp>
+#include <boost/serialization/is_bitwise_serializable.hpp>
 
 namespace boost {
 namespace serialization {
@@ -41,6 +42,17 @@
     ar & boost::serialization::make_nvp("second", p.second);
 }
 
+/// specialization of is_bitwise_serializable for pairs
+template <class T, class U>
+struct is_bitwise_serializable<std::pair<T,U> >
+ : public mpl::and_<is_bitwise_serializable<T>,is_bitwise_serializable<U> >
+{
+};
+
+template <class T, class U>
+struct implementation_level<std::pair<T,U> >
+ : mpl::int_<object_serializable> {} ;
+
 } // serialization
 } // namespace boost
 

Modified: trunk/libs/mpi/doc/mpi.qbk
==============================================================================
--- trunk/libs/mpi/doc/mpi.qbk (original)
+++ trunk/libs/mpi/doc/mpi.qbk 2007-11-14 02:00:02 EST (Wed, 14 Nov 2007)
@@ -568,6 +568,11 @@
     struct is_mpi_datatype<gps_position> : mpl::true_ { };
   } }
 
+For non-template types we have defined a macro to simplify declaring a type
+as an MPI datatype
+
+ BOOST_IS_MPI_DATATYPE(gps_position)
+
 For composite traits, the specialization of [classref
 boost::mpi::is_mpi_datatype `is_mpi_datatype`] may depend on
 `is_mpi_datatype` itself. For instance, a `boost::array` object is
@@ -1031,6 +1036,58 @@
 
 [endsect]
 
+
+
+
+[section:performance_optimizations Performance optimizations]
+[section:serialization_optimizations Serialization optimizations]
+
+To obtain optimal performance for small fixed-length data types not containing
+any pointers it is very important to mark them using the type traits of
+Boost.MPI and Boost.Serialization.
+
+It was alredy discussed that fixed length types containing no pointers can be
+using as [classref
+boost::mpi::is_mpi_datatype `is_mpi_datatype`], e.g.:
+
+ namespace boost { namespace mpi {
+ template <>
+ struct is_mpi_datatype<gps_position> : mpl::true_ { };
+ } }
+
+or the equivalent macro
+
+ BOOST_IS_MPI_DATATYPE(gps_position)
+
+In addition it can give a substantial performance gain to turn off tracking
+and versioning for these types, if no pointers to these types are used, by
+using the traits classes or helper macros of Boost.Serialization:
+
+ BOOST_CLASS_TRACKING(gps_position,track_never)
+ BOOST_CLASS_IMPLEMENTATION(gps_position,object_serializable)
+
+[endsect]
+
+[section:homogeneous_machines Homogeneous machines]
+
+More optimizations are possible on homogeneous machines, by avoiding
+MPI_Pack/MPI_Unpack calls but using direct bitwise copy. This feature can be
+enabled by defining the macro BOOST_MPI_HOMOGENEOUS when building Boost.MPI and
+when building the application.
+
+In addition all classes need to be marked both as is_mpi_datatype and
+as is_bitwise_serializable, by using the helper macro of Boost.Serialization:
+
+ BOOST_IS_BITWISE_SERIALIZABLE(gps_position)
+
+Usually it is safe to serialize a class for which is_mpi_datatype is true
+by using binary copy of the bits. The exception are classes for which
+some members should be skipped for serialization.
+
+[endsect]
+[endsect]
+
+
 [section:c_mapping Mapping from C MPI to Boost.MPI]
 
 This section provides tables that map from the functions and constants

Modified: trunk/libs/serialization/doc/traits.html
==============================================================================
--- trunk/libs/serialization/doc/traits.html (original)
+++ trunk/libs/serialization/doc/traits.html 2007-11-14 02:00:02 EST (Wed, 14 Nov 2007)
@@ -471,6 +471,32 @@
 <tr><td><code>IsWrapper</code></td><td><code></code>is the type a wrapper?</td><td><code>mpl::false_<br>mpl::true_</code></td><td><code>mpl::false_</code></td></tr>
 </table>
 
+
+<h3><a name="tracking">Bitwise serialization</a></h3>
+Some simple classes could be serialized just by directly copying all bits
+of the class. This is, in particular, the case for POD data types containing
+no pointer members, and which are neither versioned nor tracked. Some archives,
+such as non-portable binary archives can make us of this information to
+substantially speed up Serialization.
+
+To indicate the possibility of bitwise serialization the type trait defined
+in the header
+file is_bitwise_serializable.hpp
+is used:
+<pre><code>
+namespace boost { namespace serialization {
+ template<class T>
+ struct is_bitwise_serializable
+ : public is_arithmetic<T>
+ {};
+} }
+</code></pre>
+is used, and can be specialized for other classes. The specialization
+is made easy by the corresponding macro:
+<pre><code>
+BOOST_IS_BITWISE_SERIALIZABLE(my_class)
+</code></pre>
+
 <hr>
 <p><i>&copy; Copyright Robert Ramey 2002-2004 and Matthias Troyer 2006.
 Distributed under the Boost Software License, Version 1.0. (See

Modified: trunk/libs/serialization/test/Jamfile.v2
==============================================================================
--- trunk/libs/serialization/test/Jamfile.v2 (original)
+++ trunk/libs/serialization/test/Jamfile.v2 2007-11-14 02:00:02 EST (Wed, 14 Nov 2007)
@@ -206,6 +206,7 @@
 test-suite "serialization" :
      [ test-bsl-run_files test_array ]
      [ test-bsl-run_files test_binary ]
+ [ test-bsl-run_files test_complex ]
      [ test-bsl-run_files test_contained_class ]
      [ test-bsl-run_files test_cyclic_ptrs ]
      [ test-bsl-run_files test_delete_pointer ]

Added: trunk/libs/serialization/test/test_complex.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/serialization/test/test_complex.cpp 2007-11-14 02:00:02 EST (Wed, 14 Nov 2007)
@@ -0,0 +1,57 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// test_complex.cpp
+
+// (C) Copyright 2005 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)
+
+// should pass compilation and execution
+
+#include <fstream>
+
+#include <cstdio> // remove
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{
+ using ::remove;
+}
+#endif
+
+#include "test_tools.hpp"
+#include <boost/preprocessor/stringize.hpp>
+#include BOOST_PP_STRINGIZE(BOOST_ARCHIVE_TEST)
+
+#include <boost/serialization/complex.hpp>
+
+int test_main( int /* argc */, char* /* argv */[] )
+{
+ const char * testfile = boost::archive::tmpnam(NULL);
+ BOOST_REQUIRE(NULL != testfile);
+
+ // test array of objects
+ std::complex<float> a(std::rand(),std::rand());
+ std::complex<double> b(std::rand(),std::rand());
+ {
+ test_ostream os(testfile, TEST_STREAM_FLAGS);
+ test_oarchive oa(os);
+ oa << boost::serialization::make_nvp("afloatcomplex", a);
+ oa << boost::serialization::make_nvp("adoublecomplex", b);
+ }
+ std::complex<float> a1;
+ std::complex<double> b1;
+ {
+ test_istream is(testfile, TEST_STREAM_FLAGS);
+ test_iarchive ia(is);
+ ia >> boost::serialization::make_nvp("afloatcomplex", a1);
+ ia >> boost::serialization::make_nvp("adoublecomplex", b1);
+ }
+ bool equal = (std::abs(a-a1) <= 2.*std::numeric_limits<float>::round_error()
+ && std::abs(b-b1) <= 2.*std::numeric_limits<double>::round_error() );
+
+ BOOST_CHECK(equal);
+ std::remove(testfile);
+ return EXIT_SUCCESS;
+}
+
+// EOF


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