Performance STL向量的性能(内存和速度方面)+;排序+;相等与无序_集与使用纯集

Performance STL向量的性能(内存和速度方面)+;排序+;相等与无序_集与使用纯集,performance,algorithm,c++11,stl,unordered-set,Performance,Algorithm,C++11,Stl,Unordered Set,我有以下情况: 我有一堆元素,它们不需要按连续顺序排列 我将能够在初始化期间第一次插入元素 我需要执行containerA==containerB操作 元素的数量N最多可以是100个,但是为了进行平均分析,我会说N可以是100、10k或100k 鉴于此,我的需求std::set不是一个好的选择。我可以使用push_backN*O(1)和std::sortO(NlogN)在向量中插入所有元素,并进行相等比较(N);总2N+NlogN,可轻松超过std::set内存/速度 这里已经对该主题进行了详细

我有以下情况:

  • 我有一堆元素,它们不需要按连续顺序排列
  • 我将能够在初始化期间第一次插入元素
  • 我需要执行containerA==containerB操作
  • 元素的数量
    N
    最多可以是100个,但是为了进行平均分析,我会说
    N
    可以是100、10k或100k
  • 鉴于此,我的需求std::set不是一个好的选择。我可以使用push_back
    N*O(1)
    和std::sort
    O(NlogN)
    在向量中插入所有元素,并进行相等比较(N);总
    2N+NlogN
    ,可轻松超过std::set内存/速度

    这里已经对该主题进行了详细的回顾: 在这里:

    让我们来看看,如果我使用新的无序_集会发生什么。
    N
    元素的插入(
    N*O(1))
    +相等查找(
    N
    avg.case)总计为
    2N

    现在,对于无序的_集,我需要创建一个散列器,这对我来说并不容易。我猜,对于我复杂的数据结构,仅仅是散列部分就会导致这个问题超过
    2N

    但是,为什么对于一个简单的唯一的\u ptr值插入,会有人得到以下性能结果:

    向量排序+相等似乎仍然比无序_集更有效,最多可达大量元素(100k)。无序集不使用红黑树,对吗?那么,这场表演热是从哪里来的呢

    这里有一个稍微相关的帖子:

    如果您的元素有一个简单的排序函数,并且您知道它们是不同的,那么您最好将它们放在向量中并对它们进行排序。理论上,具有良好哈希函数的基于哈希表的解决方案可以进行O(n)而不是O(n log n)的比较,但有许多缓解因素:

    • logn是一个小数字。例如,如果n是二十亿,logn是31(使用二进制日志,这通常是隐含的)

    • 标准库无序集合需要为每个元素进行分配。这实际上是规范所要求的,因为向无序集合添加元素不会使对现有元素的引用无效,这与标准库向量的情况不同

    • 对无序集合的迭代是按每个bucket进行的(同样,这在规范中),其结果是迭代涉及随机内存访问。在向量上迭代是顺序的,这对缓存友好得多

    简言之,即使排序为O(n logn),基于O(n)哈希的解决方案很可能具有较大的每元素常量,并且由于logn是一个较小的数字,因此基于向量的解决方案将更快。通常要快得多

    基于散列的解决方案的速度取决于分配器的速度,不同的标准库实现之间存在很大的差异。但是,即使是一个超级快速的分配器也不太可能给您提供有竞争力的性能,并且当您的表足够大时,哈希表的缓存不友好性将变得非常重要


    即使您有一些重复的元素,使用向量可能会更好,但这取决于您有多少重复的元素。由于哈希表占用的内存可能至少是具有相同元素数的向量的两倍,因此一个简单的经验法则可能是使用向量,只要您不希望元素数超过唯一元素数的两倍。(排序后很容易消除重复项。有一个标准的库函数可以做到这一点。)

    如果您的元素有一个简单的排序函数,并且您知道它们是不同的,那么您最好将它们放在向量中并对它们进行排序。理论上,具有良好哈希函数的基于哈希表的解决方案可以进行O(n)而不是O(n log n)的比较,但有许多缓解因素:

    • logn是一个小数字。例如,如果n是二十亿,logn是31(使用二进制日志,这通常是隐含的)

    • 标准库无序集合需要为每个元素进行分配。这实际上是规范所要求的,因为向无序集合添加元素不会使对现有元素的引用无效,这与标准库向量的情况不同

    • 对无序集合的迭代是按每个bucket进行的(同样,这在规范中),其结果是迭代涉及随机内存访问。在向量上迭代是顺序的,这对缓存友好得多

    简言之,即使排序为O(n logn),基于O(n)哈希的解决方案很可能具有较大的每元素常量,并且由于logn是一个较小的数字,因此基于向量的解决方案将更快。通常要快得多

    基于散列的解决方案的速度取决于分配器的速度,不同的标准库实现之间存在很大的差异。但是,即使是一个超级快速的分配器也不太可能给您提供有竞争力的性能,并且当您的表足够大时,哈希表的缓存不友好性将变得非常重要

    即使您有一些重复的元素,使用向量可能会更好,但这取决于您有多少重复的元素。由于哈希表占用的内存可能至少是具有相同元素数的向量的两倍,因此一个简单的经验法则可能是使用向量,只要您不希望元素数超过0的两倍