C++ 使用C+最小化内存开销+;容器(std::map和std::vector太贵)
我预计将处理大量数据记录,其中大约20个C++ 使用C+最小化内存开销+;容器(std::map和std::vector太贵),c++,c++11,vector,map,stl,C++,C++11,Vector,Map,Stl,我预计将处理大量数据记录,其中大约20个uint8_t键将有数百万个对与每个键关联(按int排序)。这些对相当轻量级,大约10字节,需要动态分配 最初,我使用的是std::map,但在研究了与向量相关的开销之后,即 总共3个机器字+sizeof(元素)*capacity() 如图所示capacity()“通常可以容纳两倍于实际数量的元素”,这似乎是有害的 我可以使用std::map来代替向量,但是对于这样的轻量级对,它的开销也变得非常昂贵 我不熟悉Boost和其他C++库,所以想知道是否有人能为
uint8_t
键将有数百万个
对与每个键关联(按int
排序)。这些对相当轻量级,大约10字节,需要动态分配
最初,我使用的是std::map
,但在研究了与向量相关的开销之后,即
总共3个机器字+sizeof(元素)
*capacity()
如图所示capacity()
“通常可以容纳两倍于实际数量的元素”,这似乎是有害的
我可以使用std::map来代替向量,但是对于这样的轻量级对,它的开销也变得非常昂贵
我不熟悉Boost和其他C++库,所以想知道是否有人能为我避免手动动态内存分配的建议提供建议?
编辑:为了澄清注释中的以下几个问题,存储的结构将包含3个简短部分(首先),并且没有进一步的数据结构。我预计
向量的长度不大于1.5*10^8,并理解这将达到~1.4 GiB(感谢@dyp)
我想问题是,如何管理向量capacity()
,从而将通过reserve()
的重新分配保持在最低限度。我还不确定<代码>收缩的TojToFIE()< <代码> >(C++ 11)< /P> < P> >关于Neelkrk关于STD::向量,而不是一个键的映射,只有256种可能性,你也可以考虑STD::数组(或者甚至是C样式数组)的键。p>
对于std::pair元素,最初的实现将它们作为std::vector集合的成员,您说
我可以使用std::map来代替向量,但是对于这样的轻量级对,每个节点~32字节的开销也变得非常昂贵
这意味着元素的int
部分是唯一的,因为您没有提到std::multimap。你可以看看Googlesparsehash
()。从项目主页:
一个非常节省内存的哈希映射实现。2位/输入开销!SparseHash库包含几个哈希映射实现,包括优化空间或速度的实现
这些哈希表实现在API上类似于SGI的哈希映射类和tr1无序映射类,但具有不同的性能特征。在C++代码中,很容易用SabeSyHasyMax或DunsiH-HasyMax替换哈希映射或无序的映射。
我以前用过,从来没有遇到过问题。您的uint8\t
键可以索引到hashmaps的(std::vector/std::array/C-array)集合KCH中。如果您愿意,您甚至可以将KCH定义为对象的集合,每个对象都包含一个hashmap,因此每个KCH[i]都可以实现一个方便的接口,用于处理该键的std::pair
对象。对于集合中的非键元素,您将有一个“bad key”元素作为默认值,该元素引用a)一个空的伪hashmap或b)一个适当处理意外键值的“bad key对象”
大概是这样的:
typedef std::pair myPair;
typedef google::sparse_hash_map myCollectionType;
typedef谷歌::稀疏散列映射::迭代器myCollectionIter;
myCollectionType dummyHashMap;
std:阵列键控阵列;
将所有keyedArray
元素初始化为dummyHashMap
,然后为有效密钥填充不同的哈希映射
类似地,对于包含对象:
class KeyedCollectionHandler {
public:
virtual bool whatever(parm);
...
private:
myCollectionType collection;
};
class BadKeyHandler : public KeyedCollectionHandler
{
public:
virtual bool whatever(parm){
// unknown or unexpected key, handle appropriately
}
...
};
BadKeyHandler badKeyHandler;
将256个键控数组元素初始化为badKeyHandler
,填写KeyedCollectionHandler
对象以获得良好的键值。结构中有什么?向量的典型大小是多少?它有最大值吗?它在编译时已知吗?@πάνταῥεῖ 这不只是对至少这个数量的元素的建议吗?你可以推出一个“平面图”,它是std::vector
,通过在操作之前对向量进行排序,你可以使用std::lower_bound
和类似的函数来执行二进制搜索。在boost中可能有一个预制的这样的结构。对我来说,数以百万计的10字节对听起来像几十兆字节。其中20个仍然可以达到数百兆字节到几十亿字节的数量级。这真的是目标机器的问题吗?您引用的答案是正确的,但可能有点误导您。他基本上是说,容量可以达到目前规模的两倍。只有当增长因子至少为2时,这种情况才会发生,即使如此,也只能在重新分配后立即发生。更典型的情况是增长系数为1.5,增加的面积约为一半,因此浪费的面积约为25%。我从未见过生长因子大于2。等于2曾经很常见,但在当前的实现中,1.5似乎是典型的。这个叫Niel Kirk的人是谁?感谢你给出了这个聪明而彻底的答案-sparsehash
似乎符合要求。您是否将sparsehash
的性能与据说更高效的densite
实现进行了比较?感谢您的热情回复。不,我没有比较稀疏散列映射和密集散列映射的性能。对于我们的需求,空间考虑不是问题,而是性能问题。对于我们所需要的,稠密的\u散列\u映射只是为了性能而粉碎了std::map。我希望稀疏实现也能给人留下深刻印象。这个页面可能也会有所帮助-它有一个指向一些性能数据以及实现细节的链接:@frasnian该链接非常棒-谢谢。现在,为了测试我的增长表现,我们可以确定map_获取时间有多相似。。。