From 5dbda8f519faeeac457cf376fc186352ec3148d7 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 13 Aug 2014 11:20:19 +0200 Subject: [PATCH] refactoring of IteratorBasedCRC32, fixes #1140 --- Algorithms/IteratorBasedCRC32.h | 105 ++++++++++++++------------------ Contractor/Prepare.cpp | 11 +++- 2 files changed, 57 insertions(+), 59 deletions(-) diff --git a/Algorithms/IteratorBasedCRC32.h b/Algorithms/IteratorBasedCRC32.h index 6c2767f0d..dd693f831 100644 --- a/Algorithms/IteratorBasedCRC32.h +++ b/Algorithms/IteratorBasedCRC32.h @@ -28,41 +28,59 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ITERATOR_BASED_CRC32_H #define ITERATOR_BASED_CRC32_H -#include "../Util/SimpleLogger.h" - -#include - #if defined(__x86_64__) && !defined(__MINGW64__) #include #endif #include // for boost::crc_32_type -#if defined(__MINGW64__) -inline void __get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx) +#include + +class IteratorbasedCRC32 { - *ecx = 0; -} -#endif + public: + bool using_hardware() const { return use_hardware_implementation; } -template class IteratorbasedCRC32 -{ - private: - typedef typename ContainerT::iterator IteratorType; - unsigned crc; + IteratorbasedCRC32() : crc(0) { use_hardware_implementation = detect_hardware_support(); } - bool use_SSE42_CRC_function; - - boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor; - - unsigned SoftwareBasedCRC32(char *str, unsigned len) + template unsigned operator()(Iterator iter, const Iterator end) { - CRC32_processor.process_bytes(str, len); - return CRC32_processor.checksum(); + unsigned crc = 0; + while (iter != end) + { + typedef typename std::iterator_traits::value_type value_type; + char *data = (char *)(&(*iter)); + + if (use_hardware_implementation) + { + crc = compute_in_hardware(data, sizeof(value_type)); + } + else + { + crc = compute_in_software(data, sizeof(value_type)); + } + ++iter; + } + return crc; + } + + private: + bool detect_hardware_support() const + { + static const int sse42_bit = 0x00100000; + const unsigned ecx = cpuid(); + const bool sse42_found = (ecx & sse42_bit) != 0; + return sse42_found; + } + + unsigned compute_in_software(char *str, unsigned len) + { + crc_processor.process_bytes(str, len); + return crc_processor.checksum(); } // adapted from http://byteworm.com/2010/10/13/crc32/ - unsigned SSE42BasedCRC32(char *str, unsigned len) + unsigned compute_in_hardware(char *str, unsigned len) { #if defined(__x86_64__) unsigned q = len / sizeof(unsigned); @@ -97,45 +115,16 @@ template class IteratorbasedCRC32 __get_cpuid(1, &eax, &ebx, &ecx, &edx); return ecx; } - - bool DetectNativeCRC32Support() +#if defined(__MINGW64__) + inline void __get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx) const { - static const int SSE42_BIT = 0x00100000; - const unsigned ecx = cpuid(); - const bool has_SSE42 = (ecx & SSE42_BIT) != 0; - if (has_SSE42) - { - SimpleLogger().Write() << "using hardware based CRC32 computation"; - } - else - { - SimpleLogger().Write() << "using software based CRC32 computation"; - } - return has_SSE42; + *ecx = 0; } +#endif - public: - IteratorbasedCRC32() : crc(0) { use_SSE42_CRC_function = DetectNativeCRC32Support(); } - - unsigned operator()(IteratorType iter, const IteratorType end) - { - unsigned crc = 0; - while (iter != end) - { - char *data = reinterpret_cast(&(*iter)); - - if (use_SSE42_CRC_function) - { - crc = SSE42BasedCRC32(data, sizeof(typename ContainerT::value_type)); - } - else - { - crc = SoftwareBasedCRC32(data, sizeof(typename ContainerT::value_type)); - } - ++iter; - } - return crc; - } + boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> crc_processor; + unsigned crc; + bool use_hardware_implementation; }; #endif /* ITERATOR_BASED_CRC32_H */ diff --git a/Contractor/Prepare.cpp b/Contractor/Prepare.cpp index 3b1b98574..d5c0208f6 100644 --- a/Contractor/Prepare.cpp +++ b/Contractor/Prepare.cpp @@ -172,7 +172,16 @@ int Prepare::Process(int argc, char *argv[]) BuildRTree(node_based_edge_list); - IteratorbasedCRC32> crc32; + IteratorbasedCRC32 crc32; + if (crc32.using_hardware()) + { + SimpleLogger().Write() << "using hardware based CRC32 computation"; + } + else + { + SimpleLogger().Write() << "using software based CRC32 computation"; + } + const unsigned node_based_edge_list_CRC32 = crc32(node_based_edge_list.begin(), node_based_edge_list.end()); node_based_edge_list.clear();