【发布时间】:2019-08-08 04:30:57
【问题描述】:
这是我上一个问题的延续。我无法理解向量占用的内存。问题骨架:
考虑一个向量,它是一个列表的集合,而列表是一个指针的集合。完全一样:
std::vector<std::list<ABC*> > vec;
ABC 是我的班级。我们在 64 位机器上工作,所以指针的大小是 8 个字节。
在我的项目流程开始时,我将此向量调整为一个数字,以便我可以将列表存储在相应的索引处。
vec.resize(613284686);
此时,向量的容量和大小将为 613284686。对。调整大小后,我在相应索引处插入列表:
// Some where down in the program, make these lists. Simple push for now.
std::list<ABC*> l1;
l1.push_back(<pointer_to_class_ABC>);
l1.push_back(<pointer_to_class_ABC>);
// Copy the list at location
setInfo(613284686, l1);
void setInfo(uint64_t index, std::list<ABC*> list>) {
std::copy(list.begin(), list.end(), std::back_inserter(vec.at(index));
}
好的。这样插入就完成了。值得注意的是:
矢量大小为:613284686 向量中的条目是:3638243731 // 通过遍历向量索引并在每个索引处添加 std::lists 的大小来计算。
现在,由于有 3638243731 个指针条目,我预计该向量占用的内存约为 30Gb。 3638243731 * 8(字节)= ~30Gb。
但是当我在内存中有这些数据时,内存峰值达到 400G。
然后我清除这个向量:
std::vector<std::list<nl_net> >& ccInfo = getVec(); // getVec defined somewhere and return me original vec.
std::vector<std::list<nl_net> >::iterator it = ccInfo.begin();
for(; it != ccInfo.end(); ++it) {
(*it).clear();
}
ccInfo.clear(); // Since it is an reference
std::vector<std::list<nl_net> >().swap(ccInfo); // This makes the capacity of the vector 0.
嗯,清除这个向量后,内存下降到 100G。这对向量来说太多了。
大家愿意纠正我在这里无法理解的地方吗?
附:我无法在较小的情况下重现它,它即将出现在我的项目中。
【问题讨论】:
-
std::list要求是支持双向迭代器。这意味着列表节点必须至少存储两个指针,加上您的数据,这些数据本身可能在单独的代理中分配。诸如列表节点之类的小分配也会对需要额外内存进行核算的内存子系统造成负担。你考虑过这些吗? -
@Chipster,实际上您也可以将其视为一个独立的问题。我的最后一个 qn 与类似的向量有关,但与自动销毁有关。请把它当作一个独立的。
-
注意:内存在被程序释放时并不总是返回给系统。有时运行时会保留它,以便以后不必再次请求它。有时在系统需要它之前它不会给予任何回报。因此,您需要小心使用哪些工具来查看程序内存。
-
@Chipster 啊,但是在我(半)可以使用一屋子 Cray XD-1 的日子里。好时光,好时光。
-
一个 std::list 大约是一个 std::list 太多了,你有六亿...