【问题标题】:std::map for small sparse collections用于小型稀疏集合的 std::map
【发布时间】:2015-05-27 08:56:53
【问题描述】:

给定一个结构MyData,其中存在许多实例(我会说最多数百万个),对于每个实例,我需要存储一个成员,该成员可能包含最多 8 个键的值。键始终是int,范围为0-7,值始终是浮点的3D 点(我们称之为Point3)。

最多包含:

Key | Value  
-------------
0   | [x,y,z]  
1   | [x,y,z]  
2   | [x,y,z]
3   | [x,y,z]
4   | [x,y,z]
5   | [x,y,z]
6   | [x,y,z]
7   | [x,y,z]

但是,在 99.9% 的情况下,它将包含 0 或 1 个键值对,例如:

Key | Value
-------------
1   | [x,y,z]  

与始终存储 8 个 Point3 的数组(每个浮点数 * 3 个值 * 8 个插槽 = 96 字节)和单个 BYTE 位,其中槽位包含有意义的值?

一般来说,我的问题是空的或几乎空的std::map的内存开销是多少?

【问题讨论】:

  • 使用向量,两全其美。无论如何,线性搜索在这种规模上可能比 bst 搜索更快。至于空地图大小:几个指针,几乎是空的:依赖于实现。
  • @Slava 谢谢。我知道您的意思是 std::vectorstruct { int i; Point3 p; },是吗?
  • 您可能想深入了解 STL 的实现,看看 std::map 是如何实现的。这可能会因一种实现而异。您也可以自己试验一下,看看会发生什么。
  • gotw.ca/publications/mill14.htm 以了解 std 容器的内存开销。我认为数组或向量在内存和速度上更有效。

标签: c++ visual-studio-2010 visual-c++


【解决方案1】:

地图的内存开销并没有那么糟糕。每个节点通常是几个词。在“不过早优化”规则下,使用地图开始肯定是可以的。

也就是说,当您进行优化时,映射将在要替换的数据结构列表中排在前面。但此时,您可以分析您实际使用的所有不同操作。键和/或值多久更改一次?这是优化前需要了解的重要信息。

[编辑] 如果我要建议一个结构,它将是std::pair<int, Point3D> 的向量。原因是这可能会提供对齐友好的 16 字节对象。我不会费心对键进行排序,因为这只对具有多个键/值对的 0.1% 节点有用。

【讨论】:

  • @Rotem:这是一个反对 std::map 的论点。 Map 有一个便宜的插入(只需要添加一个节点,并打乱几个节点指针)。插入已排序的向量通常意味着移动一半的元素。 (所以 O(log N) 与 O(N))。
【解决方案2】:

查看this 博客文章。对不同 STL 容器(包括std::map)的内存使用情况进行了非常彻底的分析,并考虑了不同的平台/编译器。

在 Visual Studio 2010 (Visual C++ 10) 附带的 64 位 STL 中:


map对map对象本身使用32个字节,那么每个map节点是26个 大于所包含对象大小的字节(可能是 32 字节 考虑到对齐和损耗后)。地图数量 地图所需的节点比地图的大小大 1。

【讨论】:

  • 我已从该链接添加了相关引用。
猜你喜欢
  • 2012-08-20
  • 2021-09-22
  • 1970-01-01
  • 1970-01-01
  • 2014-01-31
  • 1970-01-01
  • 1970-01-01
  • 2012-06-30
  • 2015-05-09
相关资源
最近更新 更多