据说,迭代遍历向量(如读取所有元素)比迭代遍历列表要快,因为优化了缓存。
网上是否有任何资源可以量化它对表现的影响程度?
此外,使用自定义链接列表会更好吗?哪些元素会被预先分配,以便它们在内存中是连续的?
这背后的想法是我想以某种不会改变的顺序存储元素。我仍然需要能够在运行时快速插入一些,但是大多数仍然是连续的,因为顺序不会改变。
元素是否连续的事实是否会对缓存产生影响,或者因为我仍然会调用list_element->next
而不是++list_element
它不能改善任何内容?
答案 0 :(得分:3)
向量和列表之间的主要区别在于,向量元素随后在预分配缓冲区内构建,而在列表元素中逐个构造。 因此,向量中的元素被授予占用连续的内存空间,而列表元素(除非某些特定情况,如自定义分配器以这种方式工作)不被授予,并且可以是&#34 ;稀疏"在记忆中。
现在,由于处理器在高速缓存上运行(比主RAM快1000倍),重新映射主内存的整个页面,如果元素是连续的,则很可能它们适合同一个内存页面因此,当迭代开始时,它们会在缓存中一起移动。继续进行时,一切都在缓存中发生,无需进一步移动数据或进一步访问较慢的RAM。
使用list-s,因为元素到处都是稀疏的,"转到下一个"表示可能不在其先前的同一内存页中的地址,因此,需要在每次迭代步骤更新缓存,在每次迭代时访问较慢的RAM。
性能差异在很大程度上取决于处理器以及主RAM和缓存使用的内存类型,以及std::allocator
(最终operator new
和{{1}的方式})已实现,因此无法给出一般数字。
(注意:差异很大意味着RAM缓存不好,但也可能意味着在list-s上执行不好)
答案 1 :(得分:3)
由于数据结构的紧凑表示,缓存一致性带来的效率提升可能相当显着。在向量与列表进行比较的情况下,紧凑表示不仅可以更好地用于读取,甚至可以更好地用于某些特定体系结构的元素插入(向量移位),如Bjarne的本文图3中所示。 Stroustrup的:
http://www2.research.att.com/~bs/Computer-Jan12.pdf
(发布商网站:http://www.computer.org/portal/web/csdl/doi/10.1109/MC.2011.353)
我认为如果这是您的计划的关键因素,您应该在您的架构上进行分析。
答案 2 :(得分:1)
不确定我是否可以解释它,但这是我的观点(我正在考虑下面的翻译机器说明:),
矢量迭代器(连续内存): 增加向量迭代器时,迭代器值只是添加对象的大小(在编译时已知)以指向下一个对象。在大多数CPU中,这最多只能有一到三条指令。
列出迭代器(链表http://www.sgi.com/tech/stl/List.html): 当您递增列表迭代器(指向对象)时,通过向指向的对象的基数添加一些数字来定位前向链接的位置,然后将其作为迭代器的新值加载。对此有多个内存访问,并且比向量迭代操作慢。