【问题标题】:reusing std::unordered_map efficiently有效地重用 std::unordered_map
【发布时间】:2021-09-26 22:42:38
【问题描述】:

我在我的程序中管理相对较小的临时字典。我的问题:重用它们(使用后使用mymap.clear())是否比使用旧的delete 并创建new 的效率要高得多?

此外,这些字典目前实现为std::unordered_map<std::string, int>。这可行,但如果(根据上述使用模式)另一个容器(stl 或不是)是可取的,我会毫不犹豫地切换这个实现。

【问题讨论】:

    标签: c++ dictionary stl unordered-map


    【解决方案1】:

    至少对于 GCC,std::unordered_map<std::string, int> 在任何时间点都有如下动态分配:

    • 1 分配给一个桶数组,每个桶将迭代器(可能实现为指针)保存到一个单链节点列表中(通常在 1 倍到 2 倍的峰值元素计数之间),或者当没有元素散列到时的哨兵迭代器状态那个桶
    • #elements allocations:有一个节点有一个 next 指针、一个哈希值(是的,它保存了它!),以及 std::stringint 数据
    • #keys 长于 15:任何std::string 对于短字符串优化(其中文本内容直接存储在std::string 对象中)来说太长,都会有一个指向动态分配的文本缓冲区的指针

    当您执行.clear() 时,后两类分配将被释放。当容器本身被销毁时,只会进行一次额外的释放。

    因此,我不希望保留 unordered_maps 后性能会有很大提升。

    如果您关心性能,请更仔细地查看您的数据。字符串长度是否有上限?如果有并且它不是很大(例如 8 或 16 字节),您可以使用开放寻址(也称为封闭哈希)获取哈希表,其中键和值直接存储在存储桶中,因此只有一个动态分配正在进行。预计这会给您带来很大的性能提升(但始终可以衡量)。

    【讨论】:

      【解决方案2】:

      不幸的是,.clear() 并没有任何性能优势,并且与仅仅获得一个新的基于节点的容器相比,它的工作量几乎相同。

      如果您知道字典的最大大小,并且它相当小,请考虑为节点使用自定义分配器。

      这样,您可能会更紧凑并节省分配开销。

      除此之外,避免在标准库之外分配数千个单独节点的其他容器也是可能的。

      【讨论】:

        【解决方案3】:

        这可行,但如果(根据上述使用模式)另一个容器(stl 与否)更可取,我会毫不犹豫地切换此实现。

        好的选择开始。如果你想试试别的:

        使用真实数据在真实场景中衡量性能,看看是否值得使用替代方案。

        【讨论】:

        【解决方案4】:

        你有介绍过吗?因为现在只是很多猜测。

        考虑std::unordered_map 上的newdelete 只需添加实例化/拆除容器本身的开销。 std::unordered_map::clear 在内部仍然会在它持有的每个对象上调用 delete,以便调用它的析构函数。可能涉及到一个花哨的分配器,它为容器元素实现了一个大小相同的槽池,以节省内存管理开销。

        根据所包含对象的复杂性,使用普通的std::vector 可能更明智,也可能更不明智

        您必须分析您的开销在哪里。 但更重要的是,如果这是您的程序的一部分,会导致统计上显着的减速,请只完成这项工作。您应该在微优化之上选择易于阅读和实现清晰。

        【讨论】:

        • 谢谢,你的观点很明显。我的麻烦是这个库将是一个大应用程序的一小部分,我需要保持尽可能小的占用空间。使用向量作为容器不是一个好的选择,因为填充字典(插入新条目或添加到现有条目)将在 UI 线程上发生,并且必须非常快。
        • @AlexCohn:那么在真正的计算机(不是理论上的compsci讲座机器)上,向量实际上可能是最佳的选择,因为低于一定的大小阈值对缓存层次结构要好得多。对于一个向量,您只进行一次单一的大分配(使用std::vector::reserve),然后在内存中拥有连续的元素,而使用地图时,它是很多不连贯的小分配,到处都是。跨度>
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-16
        • 1970-01-01
        相关资源
        最近更新 更多