Skip to content

Commit

Permalink
avoid usage of hash_combine, instead use xxhash32
Browse files Browse the repository at this point in the history
- drops non-(gpu-)portable std::hash
- hashing in 32-bit chunks
  • Loading branch information
crocdialer committed Sep 29, 2024
1 parent 52b6704 commit d909364
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 10 deletions.
14 changes: 14 additions & 0 deletions include/vierkant/hash.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ inline uint64_t murmur3_fmix64(uint64_t k)
return k;
}

// Generate a random uint32_t from two uint32_t values
// @see: "Mark Jarzynski and Marc Olano, Hash Functions for GPU Rendering, Journal of Computer Graphics Techniques (JCGT), vol. 9, no. 3, 21-38, 2020"
// https://jcgt.org/published/0009/03/02/
uint32_t xxhash32(uint32_t lhs, uint32_t rhs)
{
const uint32_t PRIME32_2 = 2246822519U, PRIME32_3 = 3266489917U;
const uint32_t PRIME32_4 = 668265263U, PRIME32_5 = 374761393U;
uint32_t h32 = lhs + PRIME32_5 + rhs * PRIME32_3;
h32 = PRIME32_4 * ((h32 << 17) | (h32 >> (32 - 17)));
h32 = PRIME32_2 * (h32 ^ (h32 >> 15));
h32 = PRIME32_3 * (h32 ^ (h32 >> 13));
return h32 ^ (h32 >> 16);
}

template<class T>
inline void hash_combine(std::size_t &seed, const T &v)
{
Expand Down
21 changes: 11 additions & 10 deletions include/vierkant/linear_hashmap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ class linear_hashmap
public:
using key_t = K;
using value_t = V;
using hash_fn = std::function<uint64_t(uint64_t)>;
using hash_fn = std::function<uint32_t(uint32_t)>;
// using hash_fn = std::function<uint64_t(uint64_t)>;
static_assert(key_t() == key_t(), "key_t not comparable");

linear_hashmap() = default;
Expand Down Expand Up @@ -132,26 +133,26 @@ class linear_hashmap
static_assert(sizeof(storage_item_t) == sizeof(key_t) + sizeof(value_t),
"alignment/size requirements not met for key_t");

inline uint64_t hash(const key_t &key) const
inline uint32_t hash(const key_t &key) const
{
constexpr uint32_t num_hashes = sizeof(key_t) / sizeof(uint64_t);
constexpr uint32_t num_excess_bytes = sizeof(key_t) % sizeof(uint64_t);
auto ptr = reinterpret_cast<const uint64_t *>(&key), end = ptr + num_hashes;
size_t h = 0;
for(; ptr != end; ++ptr) { vierkant::hash_combine(h, m_hash_fn(*ptr)); }
constexpr uint32_t num_hashes = sizeof(key_t) / sizeof(uint32_t);
constexpr uint32_t num_excess_bytes = sizeof(key_t) % sizeof(uint32_t);
uint32_t h = 0;
auto ptr = reinterpret_cast<const uint32_t *>(&key), end = ptr + num_hashes;
for(; ptr != end; ++ptr) { h = vierkant::xxhash32(h, m_hash_fn(*ptr)); }
if constexpr(num_excess_bytes)
{
auto end_u8 = reinterpret_cast<const uint8_t *>(end);
uint64_t tail = 0;
uint32_t tail = 0;
for(uint32_t i = 0; i < num_excess_bytes; ++i) { tail |= end_u8[i] << (i * 8); }
vierkant::hash_combine(h, m_hash_fn(tail));
h = vierkant::xxhash32(h, m_hash_fn(tail));
}
return h;
}
uint64_t m_capacity{};
std::atomic<uint64_t> m_num_elements;
std::unique_ptr<storage_item_t[]> m_storage;
hash_fn m_hash_fn = vierkant::murmur3_fmix64;
hash_fn m_hash_fn = vierkant::murmur3_fmix32;
mutable std::shared_mutex m_mutex;
};
}// namespace vierkant
10 changes: 10 additions & 0 deletions shaders/utils/random.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ uint hash(uint a)
return a;
}

uint murmur3_fmix32(uint h)
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}

////! random number generation using pcg32i_random_t, using inc = 1. Our random state is a uint.
//uint rng_step(uint rng_state)
//{
Expand Down

0 comments on commit d909364

Please sign in to comment.