Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r61784 - in sandbox/hash/boost: . hash
From: me22.ca+boost_at_[hidden]
Date: 2010-05-04 21:08:43


Author: smcmurray
Date: 2010-05-04 21:08:43 EDT (Tue, 04 May 2010)
New Revision: 61784
URL: http://svn.boost.org/trac/boost/changeset/61784

Log:
hash: have pack delegate to memcpy when safe to do so, for a major speed boost
Text files modified:
   sandbox/hash/boost/hash.hpp | 1
   sandbox/hash/boost/hash/pack.hpp | 130 +++++++++++++++++++++++++++++++++------
   sandbox/hash/boost/hash/stream_preprocessor.hpp | 2
   3 files changed, 111 insertions(+), 22 deletions(-)

Modified: sandbox/hash/boost/hash.hpp
==============================================================================
--- sandbox/hash/boost/hash.hpp (original)
+++ sandbox/hash/boost/hash.hpp 2010-05-04 21:08:43 EDT (Tue, 04 May 2010)
@@ -9,6 +9,7 @@
 #ifndef BOOST_HASH_HPP
 #define BOOST_HASH_HPP
 
+#include <boost/hash/badhash.hpp>
 #include <boost/hash/cubehash.hpp>
 #include <boost/hash/md4.hpp>
 #include <boost/hash/md5.hpp>

Modified: sandbox/hash/boost/hash/pack.hpp
==============================================================================
--- sandbox/hash/boost/hash/pack.hpp (original)
+++ sandbox/hash/boost/hash/pack.hpp 2010-05-04 21:08:43 EDT (Tue, 04 May 2010)
@@ -17,11 +17,80 @@
 
 #ifndef BOOST_HASH_NO_OPTIMIZATION
 #include <boost/detail/endian.hpp>
+#include <boost/utility/enable_if.hpp>
 #endif
 
 namespace boost {
 namespace hash {
 
+#ifndef BOOST_HASH_NO_OPTIMIZATION
+
+template <int UnitBits,
+ int InputBits, int OutputBits,
+ typename InT, typename OutT>
+struct host_can_memcpy {
+ static bool const value =
+ !(UnitBits % CHAR_BIT) &&
+ InputBits >= UnitBits &&
+ OutputBits >= UnitBits &&
+ sizeof(InT )*CHAR_BIT == InputBits &&
+ sizeof(OutT)*CHAR_BIT == OutputBits;
+};
+
+template <typename Endianness,
+ int InputBits, int OutputBits,
+ typename InT, typename OutT>
+struct can_memcpy {
+ static bool const value =
+ InputBits == OutputBits &&
+ sizeof(InT) == sizeof(OutT);
+};
+
+template <int UnitBits,
+ int InputBits, int OutputBits,
+ typename InT, typename OutT>
+struct can_memcpy<stream_endian::host_unit<UnitBits>,
+ InputBits, OutputBits,
+ InT, OutT>
+ : host_can_memcpy<UnitBits, InputBits, OutputBits, InT, OutT> {};
+
+#ifdef BOOST_LITTLE_ENDIAN
+template <int UnitBits,
+ int InputBits, int OutputBits,
+ typename InT, typename OutT>
+struct can_memcpy<stream_endian::little_unit_big_bit<UnitBits>,
+ InputBits, OutputBits,
+ InT, OutT>
+ : host_can_memcpy<UnitBits, InputBits, OutputBits, InT, OutT> {};
+template <int UnitBits,
+ int InputBits, int OutputBits,
+ typename InT, typename OutT>
+struct can_memcpy<stream_endian::little_unit_little_bit<UnitBits>,
+ InputBits, OutputBits,
+ InT, OutT>
+ : host_can_memcpy<UnitBits, InputBits, OutputBits, InT, OutT> {};
+#endif
+
+#ifdef BOOST_BIG_ENDIAN
+template <int UnitBits,
+ int InputBits, int OutputBits,
+ typename InT, typename OutT>
+struct can_memcpy<stream_endian::big_unit_big_bit<UnitBits>,
+ InputBits, OutputBits,
+ InT, OutT>
+ : host_can_memcpy<UnitBits, InputBits, OutputBits, InT, OutT> {};
+template <int UnitBits,
+ int InputBits, int OutputBits,
+ typename InT, typename OutT>
+struct can_memcpy<stream_endian::big_unit_little_bit<UnitBits>,
+ InputBits, OutputBits,
+ InT, OutT>
+ : host_can_memcpy<UnitBits, InputBits, OutputBits, InT, OutT> {};
+#endif
+
+#endif
+
+
 template <typename Endianness,
           int InputBits, int OutputBits,
           bool Explode = (InputBits > OutputBits),
@@ -34,18 +103,16 @@
                    Bits, Bits,
                    false, false> {
 
- template <typename InputType, typename OutputType>
- static void pack_n(InputType const *in, size_t in_n,
- OutputType *out) {
- unsigned i = 0;
- for (unsigned j = 0; j < in_n; ++j) {
- out[i++] = in[j];
- }
+ template <typename InIter, typename OutIter>
+ static void pack_n(InIter in, size_t in_n,
+ OutIter out) {
+ while (in_n--) *out++ = *in++;
     }
 
- template <typename IterT1, typename IterT2>
- void pack(IterT1 b1, IterT1 e1, IterT2 b2) {
- while (b1 != e1) *b2++ = *b1++;
+ template <typename InIter, typename OutIter>
+ static void pack(InIter in, InIter in_e,
+ OutIter out) {
+ while (in != in_e) *out++ = *in++;
     }
 
 };
@@ -61,7 +128,7 @@
     template <typename InIter, typename OutIter>
     static void pack_n(InIter in, size_t in_n,
                        OutIter out) {
- for (unsigned j = 0; j < in_n; ++j) {
+ while (in_n--) {
             typedef typename std::iterator_traits<InIter>::value_type InValue;
             InValue const value = *in++;
             detail::exploder<Endianness, InputBits, OutputBits>
@@ -94,7 +161,7 @@
     static void pack_n(InIter in, size_t in_n,
                        OutIter out) {
         size_t out_n = in_n/(OutputBits/InputBits);
- for (unsigned j = 0; j < out_n; ++j) {
+ while (out_n--) {
             typedef typename std::iterator_traits<OutIter>::value_type OutValue;
             OutValue value = OutValue();
             detail::imploder<Endianness, InputBits, OutputBits>
@@ -118,14 +185,37 @@
 };
 
 template <typename Endianness,
- int InputBits, int OutputBits,
- bool BytesOnly = !(InputBits % CHAR_BIT) && !(OutputBits % CHAR_BIT)>
-struct packer : real_packer<Endianness, InputBits, OutputBits> {};
+ int InputBits, int OutputBits>
+struct packer : real_packer<Endianness, InputBits, OutputBits> {
+
+#ifndef BOOST_HASH_NO_OPTIMIZATION
+
+ using real_packer<Endianness, InputBits, OutputBits>::pack_n;
+
+ template <typename InT, typename OutT>
+ static typename enable_if<can_memcpy<Endianness, InputBits, OutputBits,
+ InT, OutT> >::type
+ pack_n(InT const *in, size_t n,
+ OutT *out) {
+ std::memcpy(out, in, n*sizeof(InT));
+ }
+
+ template <typename InT, typename OutT>
+ static typename enable_if<can_memcpy<Endianness, InputBits, OutputBits,
+ InT, OutT> >::type
+ pack_n(InT *in, size_t n,
+ OutT *out) {
+ std::memcpy(out, in, n*sizeof(InT));
+ }
+
+#endif
+
+};
 
 template <typename Endianness,
           int InValueBits, int OutValueBits,
           typename IterT1, typename IterT2>
-void pack_n(IterT1 in, size_t in_n,
+void pack_n(IterT1 in, size_t in_n,
             IterT2 out) {
     typedef packer<Endianness, InValueBits, OutValueBits> packer_type;
     packer_type::pack_n(in, in_n, out);
@@ -134,7 +224,7 @@
 template <typename Endianness,
           int InValueBits, int OutValueBits,
           typename IterT1, typename IterT2>
-void pack_n(IterT1 in, size_t in_n,
+void pack_n(IterT1 in, size_t in_n,
             IterT2 out, size_t out_n) {
     BOOST_ASSERT(in_n*InValueBits == out_n*OutValueBits);
     pack_n<Endianness, InValueBits, OutValueBits>(in, in_n, out);
@@ -198,10 +288,8 @@
           int InValueBits, int OutValueBits,
           typename InputType, typename OutputType>
 void pack(InputType const &in, OutputType &out) {
- BOOST_STATIC_ASSERT(InputType::static_size*InValueBits ==
- OutputType::static_size*OutValueBits);
- pack_n<Endianness, InValueBits, OutValueBits>(&in[0], in.size(),
- &out[0], out.size());
+ pack_n<Endianness, InValueBits, OutValueBits>(in.data(), in.size(),
+ out.data(), out.size());
 }
 
 } // namespace hash

Modified: sandbox/hash/boost/hash/stream_preprocessor.hpp
==============================================================================
--- sandbox/hash/boost/hash/stream_preprocessor.hpp (original)
+++ sandbox/hash/boost/hash/stream_preprocessor.hpp 2010-05-04 21:08:43 EDT (Tue, 04 May 2010)
@@ -159,7 +159,7 @@
     template <typename ContainerT>
     stream_preprocessor &
     update(ContainerT const &c) {
- return update(c.begin(), c.end());
+ return update_n(c.data(), c.size());
     }
     digest_type
     end_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