【问题标题】:Why is lookup in stl::map slower than in stl::vector in my Application?为什么在我的应用程序中查找 stl::map 比查找 stl::vector 慢?
【发布时间】:2010-07-07 13:40:16
【问题描述】:

我有点吃惊,尤其是在阅读this之后。

我用

template <class T>
int GetPosition(vector<T> mVec, T element)
{
    return find(mVec.begin(), mVec.end(), element) - mVec.begin();
}

template <class T>
int GetPosition(map<T, int> mMap, T element)
{
    return mMap.find(element)->second;
}

作为模板函数来获取我的向量列表中特定元素的索引。

元素是指向对象的唯一指针,我想从中检索索引。

然后我在 for 循环中使用这个模板

for(int i = 0; i < myCount; i++)
{
  index = GetPosition(myVector, elements[i]) //or GetPosition(myMap, elements[i])
}

虽然我收集的所有信息都建议使用地图,但地图实现要慢几个数量级:使用矢量变体为 57 毫秒,而使用地图则为 70000 毫秒。

这里有些东西很糟糕,但我不知道是什么。你呢?

开发平台是MS VS 2008 Standard sp1,windows XP

【问题讨论】:

    标签: performance stl visual-c++-2008


    【解决方案1】:

    由于您是按值传递它们,因此您在每次调用时都要处理vectormap。我认为这会使结果变得毫无意义。

    将它们作为引用或常量引用传递并再次运行测试。

    template <class T>
    int GetPosition(const vector<T>& mVec, T element)
    {
        return find(mVec.begin(), mVec.end(), element) - mVec.begin();
    }
    
    template <class T>
    int GetPosition(const map<T, int>& mMap, T element)
    {
        return mMap.find(element)->second;
    }
    

    【讨论】:

    • 谢谢。在这两种情况下,这将查找成本降低到几乎没有(我的测试用例为 6 毫秒)。现在这是我犯的一个非常愚蠢的错误;)
    【解决方案2】:

    请注意,由于您的代码是在此处编写的,因此您正在按值传递向量和映射,即,您在每次调用时都重建每个的新副本。这显然占用了搜索时间。

    尝试:

    template <class T> 
    int GetPosition(const map<T, int> &mMap, T element) 
    

    【讨论】:

      【解决方案3】:

      除了像其他答案提到的那样使用引用来避免复制之外,这里的算法复杂度也有所不同。

      在大小为 n 的(未排序的)向量中查找具有 O(n) 时间复杂度,而在地图上执行相同操作具有 O(log n) 时间复杂度。

      简单解释,这意味着在向量中查找对象需要时间 K1*n,而地图需要 K2*log(n) 时间,其中 K1 和 K2 是一些常数,取决于向量的实现和地图。

      在实践中哪个更快取决于容器的大小和常量是什么(我认为可以肯定地说 K1 会更快。

      缓存一致性之类的东西也会在这里发挥作用,如果你的容器很小,所有东西都会在缓存中用于矢量而不是地图。 (使用缓存,常量也不会真正保持不变,但这是另一回事......)

      【讨论】:

      • 我建议你拿起一本介绍性的计算机科学书籍来学习一些东西,比如大 O 表示法以及基本的数据结构和算法。最大的性能优势来自于选择正确的算法和数据结构;如果您没有很好地掌握计算机科学的基础知识,那么您注定要编写次优代码。
      • 在排序列表上查找是 O(lg N)。在地图上查找应该是 O(1),而不是 O(lg N),但如果您的哈希函数导致冲突,它会降级。
      • 对于 hash 映射查找时间摊销 O(1),是的。对于 std::map 它是 O(log n)。参见例如这个sgi.com/tech/stl/SortedAssociativeContainer.html
      • 我知道 map 和 vectos 应该有不同的查找速度。它们是我首先提出问题的原因,因为我不明白为什么地图查找似乎表现更差。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-23
      • 2010-09-22
      • 2011-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多