Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用C+最小化内存开销+;容器(std::map和std::vector太贵)_C++_C++11_Vector_Map_Stl - Fatal编程技术网

C++ 使用C+最小化内存开销+;容器(std::map和std::vector太贵)

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++库,所以想知道是否有人能为

我预计将处理大量数据记录,其中大约20个
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。你可以看看Google
sparsehash
()。从项目主页:

一个非常节省内存的哈希映射实现。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_获取时间有多相似。。。