c++ - SIMD 值的合理散列?

标签 c++ hash simd unordered-map

我想用 __m128i 来测试一个简单的 hashmap,但是 C++ 提示说 hash 函数不兼容:

/Applications/Xcode.app/[...]/c++/v1/__hash_table:880:5: error: static_assert failed due to requirement [...] "the specified hash does not meet the Hash requirements"

    static_assert(__check_hash_requirements<_Key, _Hash>::value,
    ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In file included from [...] note: in instantiation of template class [...] requested here
    std::unordered_map<__m128i, std::size_t> hmap;

现在,我可以通过使用类似于以下的代码来提供哈希函数:

    class hash128i
    {
    public:
        std::size_t operator()(const __m128i &r) const
        {
            return something;
        }
    };

用我发明的东西,比如OR-ing __m128i的高64位和低64位,然后使用 std::hash.

但是,鉴于哈希函数的敏感性,我不知道这种方法是否明智。

__m128i(或其他 SIMD 变量)的良好 C++ 哈希函数是什么?

最佳答案

哈希函数的实际质量在某种程度上取决于您需要的属性以及数据的分布方式。

如果您不必防御试图用大量冲突值阻塞您的表的恶意输入,那么一个相当简单的函数就足够了。

对于短整数,Chris Wellons 已经做了相当多的 analysis使用他的 hash-prospector程序。

他说的一个不错的64位函数如下,找到了here :

uint64_t splittable64(uint64_t x)
{
    x ^= x >> 30;
    x *= UINT64_C(0xbf58476d1ce4e5b9);
    x ^= x >> 27;
    x *= UINT64_C(0x94d049bb133111eb);
    x ^= x >> 31;
    return x;
}

您可以散列 128 位整数的两半并通过 XOR 组合它们,如果您希望两半经常相同,则轮换其中之一。所以你的解决方案可能看起来像这样:

class hash128i
{
public:
    std::size_t operator()(const __m128i &r) const
    {
        uint64_t lower_hash = splittable64(static_cast<uint64_t>(r));
        uint64_t upper_hash = splittable64(static_cast<uint64_t>(r >> 64));
        uint64_t rotated_upper = upper_hash << 31 | upper_hash >> 33;
        return lower_hash ^ rotated_upper;
    }
};

如果您的哈希表要抵御恶意输入,您可能希望使用带有随 secret 钥的 key 哈希函数。看看SIPHash .

关于c++ - SIMD 值的合理散列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54765861/

相关文章:

c++ - 你如何在 C++ 中将 UINT8 转换为 UINT32?

c++ - 用于 C++ 自动添加包含头的 vscode 插件

散列的散列中的 Perl 计数器

ruby-on-rails - 如何从值数组中搜索 Ruby 散列,然后根据搜索结果返回散列?

php - 一个字符串的 md5 散列可以在一个地方与另一个地方不同吗?

c++ - 关于整数和浮点性能的 SSE4 和 SSE2 - 哪个更快?

c++ - libstdc++-6.dll 问题

arm - NEON :float32x4_t 向量中最多四个浮点值

assembly - 为什么 xmm 逻辑移位不起作用?

c++ - 如何使用 C++ 编写 vector vector 的通用打印