为什么在一个大的 std::list 上迭代这么慢?

2023-12-06

正如标题所示,我的一个程序遇到了问题,我使用 std::list 作为堆栈,并且还迭代列表的所有元素。当列表变得非常大时,程序花费的时间就太长了。

有人对此有好的解释吗?是一些堆栈/缓存行为吗?

(通过将列表更改为 std::vector 和 std::deque (顺便说一句,这是一个令人惊奇的数据结构)解决了问题,一切突然变得更快了)

编辑:我不是傻瓜,我不访问列表中间的元素。我对列表所做的唯一一件事是在末尾/开头删除/添加元素并迭代all列表的元素。 我总是使用迭代器来迭代列表。


列表的缓存位置很糟糕(不存在)。每个节点都是一个新的内存分配,并且可能是anywhere. So every当您沿着指针从一个节点到下一个节点时,您会跳转到内存中一个新的、不相关的位置。是的,这对性能有很大影响。高速缓存未命中可能比高速缓存命中慢两个数量级。在向量或双端队列中,几乎每次访问都会命中缓存。向量是一个连续的内存块,因此对其进行迭代的速度尽可能快。双端队列是几个较小的内存块,因此它会偶尔出现缓存未命中的情况,但它们仍然很少见,并且迭代仍然非常快,因为您主要获得缓存命中。

一个列表将几乎所有缓存未命中。而且性能会很糟糕。

实际上,从性能的角度来看,链表几乎不是正确的选择。

Edit: 正如评论所指出的,列表的另一个问题是数据依赖性。现代 CPU 喜欢重叠操作。但如果下一条指令取决于这条指令的结果,它就无法做到这一点。

如果你迭代一个向量,那没问题。您可以即时计算要读取的下一个地址,而无需检查内存。如果您正在阅读地址x现在,下一个元素将位于地址x + sizeof(T)其中 T 是元素类型。因此,那里没有依赖关系,CPU 可以立即开始加载下一个元素或其后的元素,同时仍然处理较早的元素。这样,我们就可以在需要时准备好数据,这进一步有助于掩盖访问 RAM 中数据的成本。

在列表中,我们需要跟踪来自节点的指针i到节点i+1,直到i+1已加载,我们甚至不知道去哪里寻找i+2。我们存在数据依赖性,因此 CPU 被迫一次读取一个节点,并且它无法提前开始读取未来的节点,因为它还不知道它们在哪里。

如果列表不全是缓存未命中,这不会是一个大问题,但由于我们遇到了大量缓存未命中,这些延迟的成本很高。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么在一个大的 std::list 上迭代这么慢? 的相关文章

  • 使用可加载内核模块修改帧缓冲区(/dev/graphics/fb0)参数

    Problem 我必须配置 Android 平台使用的各种 LCD 显示器 几乎在所有情况下 都没有针对感兴趣的 LCD 显示器免费提供的电气规格 但通过经验和逆向工程 可以很好地猜测参数 我正在尝试使用可加载内核模块来微调显示参数 也欢迎
  • 我们可以在 C# 中定义枚举的隐式转换吗?

    是否可以在 C 中定义枚举的隐式转换 可以实现这一目标的东西吗 public enum MyEnum one 1 two 2 MyEnum number MyEnum one long i number 如果没有 为什么不呢 有一个解决方案
  • 在 Windows 服务中使用 OleDb 从 Excel 读取数据?

    免责声明 我知道这是一种不好的做事方式 这是我们与客户的唯一选择 Problem 我们需要每隔 x 时间从 Excel 文件读取数据 数据通过第三方 Excel 插件不断变化 应用程序的环境是 Windows XP SP1 和 Net 2
  • 如何将 QSerialPort 模块添加到 CMake 中?

    我想将 QSerialPort 模块添加到 CMake 中 根据我的理解 我需要将QT 串口添加到 pro中 我只想使用 CMake 所以我尝试编译简单的 CMake 文件 但有错误 QtCore 正在工作 qDebug 可以毫无问题地显示
  • Linux C++ 调试器

    我正在寻找完美的 Linux C 调试器 我不期望成功 但搜索应该提供丰富的信息 我是一个非常有能力的 gdb 用户 但 STL 和 Boost 很容易压垮我的调试技能 并不是说我无法深入了解数据结构的内部结构 而是它需要很长时间 我通常会
  • ASP.NET 中的 thread.sleep

    我正在为我的网站模拟彗星实时馈送协议 因此在我的控制器中我添加 while nothing new before timeout Thread Sleep 1000 但我注意到添加此功能后整个网站变慢了 调试后我得出结论 当我打电话时Thr
  • 如何让 PCRE 与 C++ 一起使用?

    这是一个新手问题 但我希望我能尽可能清楚地表达我的问题 我正在尝试用 C 进行模式匹配 我已经从以下位置下载了 PCRE 的 Win32 版本here http gnuwin32 sourceforge net packages pcre
  • 如何从Python列表中的CSV文件的单个单元格中写入单词集?

    dataList cyclone twister thunderstorm supercell wind weatherradar storm waterspout tropicalcyclone hurricane typhoon sno
  • 从Python列表中挑选出具有特定索引的项目

    我确信在 Python 中有一种很好的方法可以做到这一点 但我对这门语言还很陌生 所以如果这是一个简单的方法 请原谅我 我有一个列表 我想从该列表中挑选某些值 我想要挑选的值是列表中索引在另一个列表中指定的值 例如 indexes 2 4
  • 如何在 Windows 8.1 上打开多个 Visual Studio 窗口? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我使用的是 Windows 7 我能够启动多个 Visual Studio 并同时工作 现在我有 Windows 8 1 操作系统 每当我
  • 为什么 ASP.Net MVC Range 属性采用类型?

    我只是想知道为什么范围验证属性可以采用类型和两个字符串作为参数 这是为了根据枚举或类似的东西验证字符串吗 另外 我想做的是找到一种简单的方法来验证必须出现在枚举中的 3 个字符的字符串 有什么建议吗 谢谢 亚历克斯 我确实发现你提到的 Ra
  • Subsonic 3 ActiveRecord 嵌套选择导致 NotIn 错误?

    我有以下 Subsonic 3 0 查询 其中包含嵌套的 NotIn 查询 public List
  • 合并大文件的最佳方法是什么?

    我必须合并数千个大文件 每个大约 200MB 我想知道合并这些文件的最佳方法是什么 行将有条件地复制到合并文件中 可以使用 File AppendAllLines 或使用 Stream CopyTo 吗 使用 File AppendAllL
  • Task.Delay 到底是如何工作的?

    他们说 Task Delay 是一个异步 Thread Sleep 为了测试这一点 我写了下面的代码 我希望立即打印 One 然后 3 秒后将打印结果变量 15 2 秒后 将打印 Two 但似乎并非如此 一 不会立即打印 3 秒后打印 On
  • 更快的 WinSock sendto()

    我使用的是 Windows Server 2008 我的程序是用 C 编写的 我在 while true 循环中使用 WinSock2 和 sendto 来发送数据包 代码如下 while true if c snd gt max c sn
  • 使用反射检测属性的访问修饰符类型

    我编写了一些代码来使用反射查看属性 我已经使用反射从类中检索了属性列表 但是我需要查明该财产是公共的还是受保护的 例如 public string Name get set protected int Age get set Propert
  • 如何以一对一/零关系更新员工和身份用户

    我正在尝试更新员工记录 也想更新身份用户 如果我先单独更新身份用户 例如 UserManager Update user Context Entry employee State System Data Entity EntityState
  • RC4 实现与 openssl 输出不匹配

    我的目标是在 C C 中实现 RC4 流密码 并确保它产生与使用时相同的输出openssl命令 按照伪代码维基百科 https en wikipedia org wiki RC4 该实现似乎有效 因为它可以加密和解密内容 但是 加密的输出与
  • 有关 Endian 性和 .Net 的详细信息?

    我有几个关于字节顺序的问题 这些问题足够相关 我保证将它们作为一个问题提出 1 字节顺序是由 Net还是由硬件决定的 2 如果是由硬件决定的 我怎样才能在C 中找出硬件的字节序 3 字节序是否影响二进制交互 例如 OR AND OR 或移位
  • Json.net 将数字属性序列化为字符串

    我正在使用 JsonConvert SerializeObject 序列化模型对象 服务器期望所有字段都是字符串 我的模型对象具有数字属性和字符串属性 我无法向模型对象添加属性 有没有办法将所有属性值序列化为字符串 我必须只支持序列化 而不

随机推荐