refactoring of IteratorBasedCRC32, fixes #1140
This commit is contained in:
parent
82ce9dfc04
commit
5dbda8f519
@ -28,41 +28,59 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef ITERATOR_BASED_CRC32_H
|
#ifndef ITERATOR_BASED_CRC32_H
|
||||||
#define ITERATOR_BASED_CRC32_H
|
#define ITERATOR_BASED_CRC32_H
|
||||||
|
|
||||||
#include "../Util/SimpleLogger.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#if defined(__x86_64__) && !defined(__MINGW64__)
|
#if defined(__x86_64__) && !defined(__MINGW64__)
|
||||||
#include <cpuid.h>
|
#include <cpuid.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
#include <boost/crc.hpp> // for boost::crc_32_type
|
||||||
|
|
||||||
#if defined(__MINGW64__)
|
#include <iterator>
|
||||||
inline void __get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
|
|
||||||
|
class IteratorbasedCRC32
|
||||||
{
|
{
|
||||||
*ecx = 0;
|
public:
|
||||||
|
bool using_hardware() const { return use_hardware_implementation; }
|
||||||
|
|
||||||
|
IteratorbasedCRC32() : crc(0) { use_hardware_implementation = detect_hardware_support(); }
|
||||||
|
|
||||||
|
template <class Iterator> unsigned operator()(Iterator iter, const Iterator end)
|
||||||
|
{
|
||||||
|
unsigned crc = 0;
|
||||||
|
while (iter != end)
|
||||||
|
{
|
||||||
|
typedef typename std::iterator_traits<Iterator>::value_type value_type;
|
||||||
|
char *data = (char *)(&(*iter));
|
||||||
|
|
||||||
|
if (use_hardware_implementation)
|
||||||
|
{
|
||||||
|
crc = compute_in_hardware(data, sizeof(value_type));
|
||||||
}
|
}
|
||||||
#endif
|
else
|
||||||
|
|
||||||
template <class ContainerT> class IteratorbasedCRC32
|
|
||||||
{
|
{
|
||||||
|
crc = compute_in_software(data, sizeof(value_type));
|
||||||
|
}
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef typename ContainerT::iterator IteratorType;
|
bool detect_hardware_support() const
|
||||||
unsigned crc;
|
|
||||||
|
|
||||||
bool use_SSE42_CRC_function;
|
|
||||||
|
|
||||||
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor;
|
|
||||||
|
|
||||||
unsigned SoftwareBasedCRC32(char *str, unsigned len)
|
|
||||||
{
|
{
|
||||||
CRC32_processor.process_bytes(str, len);
|
static const int sse42_bit = 0x00100000;
|
||||||
return CRC32_processor.checksum();
|
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/
|
// 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__)
|
#if defined(__x86_64__)
|
||||||
unsigned q = len / sizeof(unsigned);
|
unsigned q = len / sizeof(unsigned);
|
||||||
@ -97,45 +115,16 @@ template <class ContainerT> class IteratorbasedCRC32
|
|||||||
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
|
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||||
return ecx;
|
return ecx;
|
||||||
}
|
}
|
||||||
|
#if defined(__MINGW64__)
|
||||||
|
inline void __get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx) const
|
||||||
|
{
|
||||||
|
*ecx = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool DetectNativeCRC32Support()
|
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> crc_processor;
|
||||||
{
|
unsigned crc;
|
||||||
static const int SSE42_BIT = 0x00100000;
|
bool use_hardware_implementation;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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<char *>(&(*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;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ITERATOR_BASED_CRC32_H */
|
#endif /* ITERATOR_BASED_CRC32_H */
|
||||||
|
@ -172,7 +172,16 @@ int Prepare::Process(int argc, char *argv[])
|
|||||||
|
|
||||||
BuildRTree(node_based_edge_list);
|
BuildRTree(node_based_edge_list);
|
||||||
|
|
||||||
IteratorbasedCRC32<std::vector<EdgeBasedNode>> 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 =
|
const unsigned node_based_edge_list_CRC32 =
|
||||||
crc32(node_based_edge_list.begin(), node_based_edge_list.end());
|
crc32(node_based_edge_list.begin(), node_based_edge_list.end());
|
||||||
node_based_edge_list.clear();
|
node_based_edge_list.clear();
|
||||||
|
Loading…
Reference in New Issue
Block a user