|
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