稀疏哈希映射对于特定数据非常慢

2024-02-12

tl;dr:为什么关键查找sparse_hash_map对于特定数据,速度变慢约 50 倍?


我正在测试速度关键查找 for sparse_hash_map来自 Google 的稀疏哈希库,使用我编写的非常简单的 Cython 包装器。哈希表包含uint32_t键和uint16_t价值观。对于随机键、值和查询,我每秒的查找次数超过 100 万次。然而,对于特定数据,我需要的性能勉强超过 20k 查找/秒。

包装纸是here https://github.com/Pastafarianist/cython-sparsehash。运行缓慢的表是here https://drive.google.com/file/d/0B0Jnpz9ldbuHUzFuRGhUSkVtYWc/view?usp=sharing。基准测试代码是:

benchmark.pyx:

from sparsehash cimport SparseHashMap
from libc.stdint cimport uint32_t
from libcpp.vector cimport vector
import time
import numpy as np

def fill_randomly(m, size):
    keys = np.random.random_integers(0, 0xFFFFFFFF, size)
    # 0 is a special domain-specific value
    values = np.random.random_integers(1, 0xFFFF, size)
    for j in range(size):
        m[keys[j]] = values[j]

def benchmark_get():
    cdef int dummy
    cdef uint32_t i, j, table_key
    cdef SparseHashMap m
    cdef vector[uint32_t] q_keys
    cdef int NUM_QUERIES = 1000000
    cdef uint32_t MAX_REQUEST = 7448 * 2**19 - 1  # this is domain-specific

    time_start = time.time()

    ### OPTION 1 ###
    m = SparseHashMap('17.shash')

    ### OPTION 2 ###
    # m = SparseHashMap(16130443)
    # fill_randomly(m, 16130443)

    q_keys = np.random.random_integers(0, MAX_REQUEST, NUM_QUERIES)

    print("Initialization: %.3f" % (time.time() - time_start))

    dummy = 0

    time_start = time.time()

    for i in range(NUM_QUERIES):
        table_key = q_keys[i]
        dummy += m.get(table_key)
        dummy %= 0xFFFFFF  # to prevent overflow error

    time_elapsed = time.time() - time_start

    if dummy == 42:
        # So that the unused variable is not optimized away
        print("Wow, lucky!")

    print("Table size: %d" % len(m))
    print("Total time: %.3f" % time_elapsed)
    print("Seconds per query: %.8f" % (time_elapsed / NUM_QUERIES))
    print("Queries per second: %.1f" % (NUM_QUERIES / time_elapsed))

def main():
    benchmark_get()

benchmark.pyxbld(因为pyximport应在 C++ 模式下编译):

def make_ext(modname, pyxfilename):
    from distutils.extension import Extension
    return Extension(
        name=modname,
        sources=[pyxfilename],
        language='c++'
    )

run.py:

import pyximport
pyximport.install()

import benchmark
benchmark.main()

结果为17.shash are:

Initialization: 2.612
Table size: 16130443
Total time: 48.568
Seconds per query: 0.00004857
Queries per second: 20589.8

对于随机数据:

Initialization: 25.853
Table size: 16100260
Total time: 0.891
Seconds per query: 0.00000089
Queries per second: 1122356.3

密钥分布在17.shash这是 (plt.hist(np.fromiter(m.keys(), dtype=np.uint32, count=len(m)), bins=50)):

从文档上sparsehash https://sparsehash.googlecode.com/svn/trunk/doc/implementation.html and gcc https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01206_source.html#l00118似乎这里使用了简单的哈希(即x散列到x).

除了哈希冲突之外,还有什么明显的因素可能导致此行为吗?根据我的发现,集成自定义哈希函数(即重载std::hash<uint32_t>)在 Cython 包装器中。


我找到了一个可行的解决方案,但它并不漂亮。

sparsehash_wrapper.cpp:

#include "sparsehash/sparse_hash_map"
#include "stdint.h"

// syntax borrowed from
// https://stackoverflow.com/questions/14094104/google-sparse-hash-with-murmur-hash-function

struct UInt32Hasher {
    size_t operator()(const uint32_t& x) const {
        return (x ^ (x << 17) ^ (x >> 13) + 3238229671);
    }    
};

template<class Key, class T>
class sparse_hash_map : public google::sparse_hash_map<Key, T, UInt32Hasher> {};

这是一个自定义哈希函数,我可以将其集成到现有包装器中,只需进行最少的代码更改:我只需替换sparsehash/sparse_hash_map与路径sparsehash_wrapper.cpp在赛通.pxd文件。到目前为止,唯一的问题是pyximport找不到sparsehash_wrapper.cpp除非我指定完整的绝对路径.pxd.

问题确实在于冲突:重新创建具有相同内容的哈希映射后17.shash从头开始(即创建一个空映射并插入每个(键,值)对17.shash进入其中),性能达到 1M+ req/sec。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

稀疏哈希映射对于特定数据非常慢 的相关文章

随机推荐

  • APK 0(零)设备兼容性

    我正在生成一个要在商店上发布的 APK 它是现有应用程序的更新 上传到 Google Play Console 后 支持的 Android 设备 0 台设备 这是我的清单
  • vue js如何使用方法将数据从父组件、v-for循环列表传递到子组件

    我试图实现在子组件 模态组件 中显示每个项目收据数组的项目列表 但一直无法这样做 方法display receipts 是将receipts modal的数据值改为true 我可以在哪里放置 v bind 来传递数组 任何帮助深表感谢 Pa
  • 使用networkx从图中删除边

    我正在尝试转换DiGraph成n叉树并按层序或BFS显示节点 我的树与此类似 但更大 为简单起见 使用以下示例 G networkx DiGraph G add edges from n n1 n n2 n n3 G add edges f
  • 是否可以使用服务帐户访问Provisioning API?

    我的服务帐户范围是 https apps apis google com a feeds user https apps apis google com a feeds user 和 DriveScope DRIVE 我在我的服务帐户 ID
  • VS2015:警告MSB3884:找不到规则集文件

    将我的 WinForms VS2013 项目升级到 VS2015 后 我开始看到 MSB3884 找不到规则集文件 警告 Google 搜索发现了一篇 MSDN 文章 Stack Overflow 文章以及许多其他网站都指向了该文章 类似问
  • R可以识别Excel文件是否有注释单元格吗?

    我有一张 Excel 表格 xlsx 其中有一些注释的单元格 导入R后 R有什么办法可以识别注释的单元格吗 因为我必须仅对注释的单元格使用一些 if else 条件 Let s say we have this file test xlsx
  • 以逗号或分号分隔的自动完成文本框

    我想要一个TextBox支持自动完成 并允许用户输入以逗号或分号分隔的多个单词 并为每个单词提供建议 我有一个标准TextBox with textBox AutoCompleteCustomSource AddRange new appl
  • Haskell、通道、STM、线程、消息传递

    我正在尝试使用 Channels STM 在 Haskell 中实现消息传递 也许这是一个糟糕的想法 并且有更好的方法在 Haskell 中实现 使用消息传递 如果是这种情况 请告诉我 然而 我的探索提出了一些关于并发 Haskell 的基
  • Firebase Chrome 扩展 Javascript content_security_policy 清单 3

    我刚刚开始工作chrome extensions and javascript看到每个人都建议使用Manifest version 3开始 我想实施firebase进入我的扩展和旧的Manifest version 2我需要输入这个 con
  • 使用 R 和 tidyverse 将 tidy 表转换为深度嵌套列表

    我正在尝试使用 R tidyverse 将整洁的表 例如下面的示例 转换为嵌套列表 使用一些 tidyverse 魔法 我能够将其转换为深度为三的嵌套列表 但我不知道如何将其嵌套得更深 采用以下示例输入 library tidyverse
  • TFS 构建:以管理员身份运行 Powershell 脚本

    我为我们的夜间构建服务器创建了一个构建定义 构建项目 Windows 服务 后 我需要执行 Powershell 脚本来安装并启动该服务 因此 我添加了一个构建步骤来运行特定的 Powershell 脚本 然后我在 很快 夜间构建服务器上安
  • 根据原始列名称重命名列 R

    我有一个与此类似的数据框 事实上 for 循环中有 16 个 head data A tibble 1 x 4 AAA AAC AB AC 1 18 25 39 9 2 20 25 30 7 我想根据列的原始名称动态更改所有列名称 如下所示
  • 如何将 int 转换为 QString?

    有没有QString函数需要一个int并将其输出为QString Use QString number http doc qt io qt 5 qstring html number int i 42 QString s QString n
  • 是否可以在 Selenium 和 Chrome 网络驱动器上禁用加载图像(仅限 jpg 和 png)?

    在我努力提高硒测试应用程序的性能时 我想知道是否可以避免加载某些文件 例如图像 jpg 和 png 参数 disable images 禁用所有图像 包括 gif 在我看来 它可以是谷歌分析标签 我必须捕获它 是的 您可以通过指定来做到这一
  • React Native - 从库项目中,如何导入和使用包的模块

    我使用创建了一个 React Native 库项目react native create library命令为我的开发提供更加模块化的环境 因此稍后我可以将该库用于多个正在进行的应用程序项目并消除代码重复 对于 Java 它非常适合外部应用
  • Active Directory 中在线的计算机列表

    我使用这段代码输出网络上所有计算机的列表 语言是 jscript net 但这只是 C 的一个小操作 var parentEntry new DirectoryEntry parentEntry Path WinNT for var chi
  • 时刻未向从 javascript 日期创建的对象添加分钟

    我有一个方法 它接受带有时间的 javascript 日期作为输入 并确定当前日期和时间是否在 30 分钟内 但是 当我在运行时调试它时 moment add 似乎没有按预期工作几分钟 function isWithinRange myDa
  • Swift === 与 nil

    为什么以下代码在 Swift 中不起作用 if someObject nil 您必须使用 运算符进行测试 例如 if someObject nil 我认为 更像是确保实例完全相同 基本上是比较指针 而 更像是 isEqual 检查 因此我认
  • Android:使用FLAG_SECURE方法后无法截图

    出于安全原因 我想在应用程序进入后台时隐藏应用程序的内容 了解使用下面的方法可以完成这项工作 但我希望屏幕截图功能仍然有效 getWindow addFlags WindowManager LayoutParams FLAG SECURE
  • 稀疏哈希映射对于特定数据非常慢

    tl dr 为什么关键查找sparse hash map对于特定数据 速度变慢约 50 倍 我正在测试速度关键查找 for sparse hash map来自 Google 的稀疏哈希库 使用我编写的非常简单的 Cython 包装器 哈希表