【问题标题】:Which is the fastest STL data structure in C++ to iterate over a large number of elements?哪个是 C++ 中迭代大量元素的最快的 STL 数据结构?
【发布时间】:2015-09-10 07:48:43
【问题描述】:

元素遵循某个属性,其中每个元素通过某种复杂关系与其前一个元素相关(假设没有已知的简单公式可以找出第 i 个元素)我想计算这个系列中某个元素的值,我必须为此计算每个元素的值,并在此过程中遍历完整的元素列表。

我使用了一个数组,它可能导致了一些内存分配错误(SIGABRT)。 我使用了一个向量,同样的错误。可能是因为元素的数量很大并且它们是连续存储的。 然后我使用了一个列表,没有这样的错误,但它花费的时间超过了可接受的时间限制。

【问题讨论】:

  • 您的描述中没有任何内容说明您需要存储整个序列(而不是计算它)的原因。如果您解释了原因,那么您可能会得到更好的答案。
  • 一个列表实际上占用了更多内存,但不是连续的。尽管如此,在这个 64 位计算的时代,连续内存限制实际上已经消失了。您确实编译为 64 位,对吗?
  • “我使用了向量,同样的错误。” - 你是如何使用vector的?如果您可以reserve() 预先提供足够的容量,则可以避免潜在的代价高昂的调整大小,包括暂时需要大约 3 倍于当前元素使用的内存(其中 2/3 需要是连续的)。如果你不能合理地提前预留,那么松元瑶的建议就像deque 分配更小的块。
  • 您可以存储中间值并通过从最近的存储邻居计算来插入缺失的值。

标签: c++ stl


【解决方案1】:

你可以试试std::deque

与 std::vector 不同,双端队列的元素不被存储 连续的:典型的实现使用一个单独的序列 分配固定大小的数组。

deques 上常见操作的复杂度(效率)为 如下:

Random access - constant O(1)
Insertion or removal of elements at the end or beginning - constant O(1)
Insertion or removal of elements - linear O(n)

【讨论】:

  • 该死的,我正要这么说;-)
  • 如果您对vectordeque 的顺序访问进行基准测试,vector 将会获胜。
  • @MaximEgorushkin 我知道,但 OP 明确表示他不能使用数组或向量(可能是因为连续存储),但他想要比列表更快的东西。
  • @songyuanyao OP 说它因未知原因崩溃。
  • @MaximEgorushkin 那将是另一个问题...为什么我的代码在使用数组或向量时崩溃了?
【解决方案2】:

现代 CPU 最擅长顺序访问。在两个方向上按顺序迭代数组时,您可以获得最快的访问时间,因为硬件预取器旨在识别这种访问模式并希望在您开始访问之前将数据预取到 L1 缓存中。

换句话说,std::vector<>std::array<> 在顺序迭代方面是最快的。

有关详细信息,请参阅“英特尔® 64 和 IA-32 架构优化参考手册”2.2.5.4 数据预取:

... 预取器的目标是自动预测程序将要使用哪些数据。如果此数据不在执行核心或内部缓存附近,则预取器将其从下一级缓存层次结构中提取出来 和记忆。预取有以下效果:

• 如果数据按照程序中使用的顺序依次排列,则会提高性能。

• 如果访问模式是稀疏的而不是本地的,可能会由于带宽问题而导致性能轻微下降。

• 在极少数情况下,如果算法的工作集被调整为占用大部分缓存并且不需要的预取驱逐程序所需的行,硬件预取器可能会由于 L1 的缓存容量而导致性能严重下降。

数据预取到 L1 数据缓存

当满足以下条件时,加载操作触发数据预取:

• 加载来自回写内存类型。

• 预取的数据与触发它的加载指令位于同一 4K 字节页面内。

• 管道中没有围栏。

• 没有多少其他加载未命中正在进行中。

• 没有源源不断的商店。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-18
    • 2013-02-21
    • 2021-10-17
    相关资源
    最近更新 更多