Optimize hash performance with custom unroll

This commit is contained in:
Andrea Mazzoleni 2026-09-30 13:31:34 +02:00
parent 31570ae473
commit edb3cacb77
5 changed files with 29 additions and 32 deletions

View file

@ -217,7 +217,10 @@ $(CLI_PREFIX)sync.$(OBJEXT): $(CLI_INCLUDES)
$(CLI_PREFIX)thermal.$(OBJEXT): $(CLI_INCLUDES)
$(CLI_PREFIX)touch.$(OBJEXT): $(CLI_INCLUDES)
$(CLI_PREFIX)unixapp.$(OBJEXT): $(CLI_INCLUDES)
$(CLI_PREFIX)util.$(OBJEXT): $(CLI_INCLUDES)
$(CLI_PREFIX)util.$(OBJEXT): $(CLI_INCLUDES) \
$(srcdir)/cmdline/murmur3.c \
$(srcdir)/cmdline/spooky2.c \
$(srcdir)/cmdline/museair.c
# Add the .version file in the distribution
dist-hook:

View file

@ -26,42 +26,16 @@ static inline uint32_t fmix32(uint32_t h)
}
/*
* Warning!
* Don't declare these variables static, otherwise the gcc optimizer
* may generate very slow code for multiplication with these constants,
* like:
-> .cpp
k1 *= c1;
-> .asm
152: 8d 14 80 lea (%eax,%eax,4),%edx
155: 8d 14 90 lea (%eax,%edx,4),%edx
158: c1 e2 03 shl $0x3,%edx
15b: 29 c2 sub %eax,%edx
15d: 8d 14 d2 lea (%edx,%edx,8),%edx
160: 8d 14 90 lea (%eax,%edx,4),%edx
163: 8d 14 d0 lea (%eax,%edx,8),%edx
166: 8d 14 90 lea (%eax,%edx,4),%edx
169: 8d 14 50 lea (%eax,%edx,2),%edx
16c: 8d 14 90 lea (%eax,%edx,4),%edx
16f: 8d 14 92 lea (%edx,%edx,4),%edx
172: 8d 14 50 lea (%eax,%edx,2),%edx
175: 8d 04 d0 lea (%eax,%edx,8),%eax
178: 8d 14 c5 00 00 00 00 lea 0x0(,%eax,8),%edx
17f: 29 d0 sub %edx,%eax
* resulting in speeds of 500 MB/s instead of 3000 MB/s.
*
* Verified with gcc 4.4.4 compiling with :
*
* g++ -g -c -O2 MurmurHash3.cpp -o MurmurHash3.o
* Non-static variables are intentionally used instead of static const
* because keeping these constants in CPU registers yields measurably
* higher throughput than using 32-bit immediate constants in imul.
*/
uint32_t c1 = 0x239b961b;
uint32_t c2 = 0xab0e9789;
uint32_t c3 = 0x38b34ae5;
uint32_t c4 = 0xa1e38b93;
void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, void* digest)
static void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, void* digest)
{
const uint8_t* p;
const uint8_t* end;
@ -77,6 +51,11 @@ void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, voi
end = p + (size & ~15);
/* body */
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC unroll 8
#elif defined(__clang__)
#pragma unroll 8
#endif
while (p < end) {
uint32_t k1 = util_read32(p + 0);
uint32_t k2 = util_read32(p + 4);

View file

@ -190,6 +190,11 @@ static void MuseAirLoong(const void* bytes, size_t len, const uint8_t* seed, uin
state[5] ^= seed_b & MASK_K;
if (unlikely(q > u64x(12))) {
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC unroll 2
#elif defined(__clang__)
#pragma unroll 2
#endif
do {
state[0] ^= util_read64(p + u64x(0));
state[1] ^= util_read64(p + u64x(1));

View file

@ -96,7 +96,7 @@
//
#define sc_const 0xdeadbeefdeadbeefULL
void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest)
static void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest)
{
uint64_t h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11;
uint8_t buf[sc_blockSize];
@ -117,6 +117,11 @@ void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t*
end = p + nblocks * sc_blockSize;
/* body */
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC unroll 1
#elif defined(__clang__)
#pragma unroll 1
#endif
while (p < end) {
Mix(p, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
p += sc_blockSize;

View file

@ -110,6 +110,11 @@ uint32_t crc32c_shift(uint32_t crc, size_t size);
*/
static inline uint32_t crc32c_gen_plain(uint32_t crc, const unsigned char* ptr, size_t size)
{
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC unroll 1
#elif defined(__clang__)
#pragma unroll 1
#endif
while (size >= 4) {
crc ^= ptr[0] | (uint32_t)ptr[1] << 8 | (uint32_t)ptr[2] << 16 | (uint32_t)ptr[3] << 24;
crc = CRC32C_3[crc & 0xff] ^ CRC32C_2[(crc >> 8) & 0xff] ^ CRC32C_1[(crc >> 16) & 0xff] ^ CRC32C_0[crc >> 24];