【问题标题】:std::list vs std::vector iterationstd::list 与 std::vector 迭代
【发布时间】:2012-05-07 03:33:52
【问题描述】:

据说由于优化了缓存,遍历向量(如读取其所有元素)比遍历列表更快。

网络上是否有任何资源可以量化它对性能的影响程度?

另外,使用自定义链表会更好吗,哪些元素会被预先分配,以便它们在内存中是连续的?

这背后的想法是我想以不会改变的特定顺序存储元素。我仍然需要能够在运行时在中间快速插入一些,但它们中的大多数仍然是连续的,因为顺序不会改变。

元素是连续的这一事实是否会对缓存产生影响,或者因为我仍然会调用 list_element->next 而不是 ++list_element 它并没有改善任何东西?

【问题讨论】:

  • “另外,使用自定义链表会更好吗,哪些元素会被预先分配以便它们在内存中是连续的?”你是说矢量?
  • std::list 的主要要求是从列表中的任何位置插入和删除单个元素的时间是恒定的。这与在内存中连续的元素不兼容。
  • @jules 首先,你确定这部分代码需要优化了吗?
  • @LuchianGrigore 不。他所说的是将所有列表的节点分配在一个未分段的内存块中。它们仍然会通过nextprev 指针相互引用。
  • @juanchopanza:他不希望所有元素是连续的,只是大多数,很少有插入离开顺序容器并返回。考虑一个向量,其中元素 N 指向向量之外的元素,该向量又指向元素 N+1。容器作为一个整体是不连续的,但范围 [0..N] 和 [N..M] 是连续的(N 是向量而不是列表的索引)。这种设计实际上可能有意义,但我会很高兴知道对性能的实际影响......

标签: c++ list stl vector iteration


【解决方案1】:

不确定我是否可以正确解释,但这是我的观点(我正在按照下面翻译的机器指令进行思考:),

向量迭代器(连续内存): 当您增加向量迭代器时,迭代器值只是简单地添加对象的大小(在编译时已知)以指向下一个对象。在大多数 CPU 中,这最多是一到三个指令。

列表迭代器(链表http://www.sgi.com/tech/stl/List.html): 当你增加一个列表迭代器(指向的对象)时,前向链接的位置是通过在指向的对象的基础上添加一些数字来定位的,然后作为迭代器的新值加载。有不止一个内存访问,并且比向量迭代操作慢。

【讨论】:

    【解决方案2】:

    向量和列表之间的主要区别在于,向量中的元素是在预先分配的缓冲区中随后构造的,而列表中的元素是一个接一个地构造的。 因此,向量中的元素被授予占用连续内存空间,而列表元素(除非某些特定情况,例如以这种方式工作的自定义分配器)不被授予如此,并且可以在周围“稀疏”记忆。

    现在,由于处理器在重新映射主内存的整个页面的高速缓存(其速度可能比主 RAM 快 1000 倍)上运行,因此如果元素是连续的,则它们很可能适合相同的内存页面因此在迭代开始时在缓存中一起移动。在继续进行时,一切都发生在缓存中,无需进一步移动数据或进一步访问较慢的 RAM。

    对于list-s,由于元素在任何地方都是稀疏的,“去下一个”是指一个地址可能不在其前一个内存页面中,因此每次迭代都需要更新缓存步骤,在每次迭代时访问较慢的 RAM。

    性能差异很大程度上取决于处理器和用于主 RAM 和缓存的内存类型,以及 std::allocator(最终是 operator newmalloc)的实现方式,所以不可能给出一个普遍的数字。 (注意:巨大的差异意味着 RAM 对缓存的影响很差,但也可能意味着在 list-s 上的实现很差)

    【讨论】:

      【解决方案3】:

      由于数据结构的紧凑表示,缓存一致性带来的效率提升可能相当显着。在与列表相比的向量的情况下,紧凑表示不仅可以更好地用于读取,甚至可以用于某些特定架构的高达 500K 元素数量级的元素的插入(向量中的移动),如 Bjarne 的本文图 3 所示斯特鲁普:

      http://www2.research.att.com/~bs/Computer-Jan12.pdf

      (发布者网站:http://www.computer.org/portal/web/csdl/doi/10.1109/MC.2011.353

      我认为如果这对你的程序来说是一个关键因素,你应该在你的架构上对其进行分析。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-19
        • 2020-08-20
        • 1970-01-01
        • 2017-02-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-22
        相关资源
        最近更新 更多