【问题标题】:Choosing a STL Container for a very large list为非常大的列表选择 STL 容器
【发布时间】:2011-08-09 07:36:53
【问题描述】:

我有一个非常大的项目列表(约 200 万),我想优化访问速度。我使用迭代器 (++it) 遍历项目。
现在代码是使用std:map<std::wstring, STRUCT>实现的。
我想知道是否值得用std::deque<std::pair<std::wstring, STRUCT>> 更改std::map。我认为我将具有使用指针算法的优势并最大限度地减少缓存未命中。值得吗?
我知道分析是答案,但在实施之前我需要一个意见......

【问题讨论】:

  • 您如何访问这些项目?如果您只是在遍历它们,那么地图似乎是错误的结构,所以大概您正在做一些查找?您能否为问题添加更多细节?
  • 我在 STRUCT 中搜索一些值。我迭代了很多,我使用迭代器(++it),但我可能会切换到 std::for_each 虽然我不认为这是一个很大的优势
  • Jeff 的意思是:你当初为什么选择地图?除了迭代之外,您还做什么其他

标签: c++ optimization stl


【解决方案1】:

如果您事先知道大小,那么 std::Vector 显然是您的对象不会太大的方法。

std::vector<Object> list;
list.reserve(2000000);

然后像往常一样填充它。

这是最快且内存消耗最少的方法。但是,您需要能够分配足够的连续内存。但除非您的对象有 1kb 大,否则应该不是问题。

【讨论】:

  • 1 KB 乘以 2000000 个对象对我来说听起来是个问题
  • 我事先不知道尺寸。这就是为什么我在考虑deque。 STRUCT 的大小比 1k 多一点
  • @viktor 你需要 2Gb 的连续文件。确实可能是个问题。然而,1kb 的数据结构相当少见(可能意味着你在滥用 C 数组而不是向量); @cprogrammer 正如大家所说,双端队列是要走的路
  • 在实践中,即使是几个字节也可能成为问题。尝试一次分配几 MB 的数据可能并不总是成功。也就是说,有时我希望能够自定义双端队列的桶大小以填充 4KB 块。
  • @Mattieu:“尝试一次分配几 MB 的数据可能并不总是成功”,是的,让我们记住 90 年代...
【解决方案2】:

使用双端队列,您将失去(或必须重新实现)键值对的优势。如果它对您的数据不是必需的,我会考虑使用双端队列。

【讨论】:

  • 为什么?如果对象按其键排序,则可以使用二进制搜索进行查找,因此 OP 不会丢失任何内容:)
  • @Grigory: 相反,binary_searchlower_boundupper_bound 等...由于内存块的连续性,通常比它们的 std::map 表兄弟更快(取决于 @ 987654325@ 执行)。所以它不应该更慢,而且可以更快。
  • @Matthieu:这就是我要说的。
【解决方案3】:

一般来说,如果您只在这个集合中进行搜索(没有插入/删除),您最好使用排序的顺序硬币容器,如双端队列或向量。然后,您可以使用简单的二进制搜索来查找所需的元素。使用顺序容器的优点是它在内存使用方面更好,实现非常简单,并提供更好的引用局部性。我会使用 vector 编写一个版本的代码,使用 deque 编写另一个版本的代码,然后在性能方面比较它们以决定在最终版本中使用哪一个。

但是,如果您的结构需要更新(需要插入新元素或必须频繁删除旧元素),则 map 是更好的选择。或者,您只需要完全删除 STL 容器并使用内存数据库(请参阅 SQLite),但这在很大程度上取决于您要解决的问题。

【讨论】:

  • 我不需要搜索元素,一旦填充了数据,只会执行读取操作。不幸的是,我不能利用排序数据的优势,因为按键排序并不重要,而且不可能通过 STRUCT 排序(我对结构中的多个值感兴趣)
  • 为什么不能按struct的字段排序?假设您对结构中的字段 A、B 和 C 感兴趣。为您的结构编写一个运算符
【解决方案4】:

迭代速度最快的容器通常是vector,因此如果您想以牺牲其他一切为代价来优化迭代,请使用它。

当然,应用程序的整体性能取决于您迭代的次数,以及您最初构建数据的方式。对于一个简单的测试,一旦你的地图被填充,你可以从它构造一个向量,如下所示:

vector<pair<K,V> > myvec(mymap.begin(), mymap.end());

其中 K 和 V 是映射的键和值类型。然后只需使用向量迭代器代替映射迭代器并比较性能。

当然,如果你以后想修改地图,那么通常不适合以牺牲其他一切为代价来优化迭代。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-17
    • 1970-01-01
    • 1970-01-01
    • 2014-03-10
    • 1970-01-01
    • 1970-01-01
    • 2019-02-13
    相关资源
    最近更新 更多