由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
Programming版 - 请问释放容器内存的方法
相关主题
突然发现现在很反感malloc了why do we still use dynamic allocation?
寻找一个allocator 做一个指定内存空间内的 alloc/free什么是OS Memory management and heap structure?
请教关于C++内存管理c+= 怎么实现 hashtable 的?
STL vector的clear如何强制归还系统?请问用mmap分配的共享内存如何回收?
STL/vector引用成员变量。奇怪的问题:关于一个简单的malloc()小程序 (转载)
vector的析构问题Help! Read random number of lines in a input file.
bad_alloc 问题请教C++ STL中priority_queue模板参数中的Compare函数
"brk()" 和 mmap() 有什么区别? (转载)请问关于 share memory 的问题
相关话题的讨论汇总
话题: 内存话题: 释放话题: std话题: vector话题: swap
1 (共1页)
y**b
发帖数: 10166
1
std::vector vec;
vec.resize(10000000,-1);
vec.clear(); //并不真正释放内存
std::vector().swap(vec);//通常用来释放内存的trick
试验了一下,swap能彻底释放内存;可是这个方法对unordered_set只能释放部分内存:
std::unordered_set uos;
for (int i = 0; i < 10000000; ++i)
uos.insert(i);
uos.clear(); //并不真正释放内存
std::unordered_set().swap(uos); //大约释放1/3内存
换成boost::unordered_set也是同样结果。请问有没有什么办法能释放得彻底一些?
c****e
发帖数: 1453
2
什么叫做不释放内存,你怎么察看的?
y**b
发帖数: 10166
3
linux下面我直接用ps或top命令查看的,可以清楚看到各个进程的内存消耗。
swap这个方法我用google搜索到的,似乎是通用的一个trick; effective stl里面也有
提到。
下面是源码,只有swap之后进程的内存消耗才降到近乎0(getchar的时候察看)。
#include
#include
#include
int main () {
std::vector vec;
vec.resize(10000000,-1);
std::cout << "resize finished." << std::endl;
getchar();
vec.clear();
std::cout << "clear finished." << std::endl;
getchar();
std::vector().swap(vec);
std::cout << "swap finished." << std::endl;
getchar();
return 0;
}

【在 c****e 的大作中提到】
: 什么叫做不释放内存,你怎么察看的?
c****e
发帖数: 1453
4
The heap implementation caches it. You can use your own allocator.

【在 y**b 的大作中提到】
: linux下面我直接用ps或top命令查看的,可以清楚看到各个进程的内存消耗。
: swap这个方法我用google搜索到的,似乎是通用的一个trick; effective stl里面也有
: 提到。
: 下面是源码,只有swap之后进程的内存消耗才降到近乎0(getchar的时候察看)。
: #include
: #include
: #include
: int main () {
: std::vector vec;
: vec.resize(10000000,-1);

y**b
发帖数: 10166
5
自己写allocator,能改变这种行为吗?

【在 c****e 的大作中提到】
: The heap implementation caches it. You can use your own allocator.
n******t
发帖数: 4406
6
都要这么搞了,用C好了。
stl就是个让你别惹事好好用的东西。

存:

【在 y**b 的大作中提到】
: 自己写allocator,能改变这种行为吗?
y**b
发帖数: 10166
7
还真是没惹它,就是有这种客观需要,比如在supercomputer上并行5000个进程运行100
小时,每隔一小时root process从其他4999个进程合并一次数据用来输出,这个数据量
相当可观,如果不及时释放内存,则下一个小时计算时段内内存可能就不够用;如果
完全释放了就能顺利计算下去。因为数据之间有少许冗余,用unordered_set也是很顺理
成章的事情。而且这些数据都是oop的对象,不用stl来操作以及boost.mpi来串行化和
传递的话,其复杂程度太大。

【在 n******t 的大作中提到】
: 都要这么搞了,用C好了。
: stl就是个让你别惹事好好用的东西。
:
: 存:

c****e
发帖数: 1453
8
should be. Search to find an example.

【在 y**b 的大作中提到】
: 自己写allocator,能改变这种行为吗?
y**b
发帖数: 10166
9
折腾了几天,感觉这个问题可能无解,也许C++标准就不认为这是个问题。
先后测试了四种allocator,没有一个能生效,这里也有人提到:
http://bytes.com/topic/c/answers/133169-return-memory-os
1. new/delete:
http://www.josuttis.com/cppcode/allocator.html
2. malloc/free (跟1类似):
http://www.usidcbbs.com/read-htm-tid-4896-fpage-3.html
3. boost::pool_allocator, boost::fast_pool_allocator:
http://www.boost.org/doc/libs/1_53_0/libs/pool/doc/html/boost_p
rfaces.html#boost_pool.pool.interfaces.interfaces.pool_allocator
无论release_memory, purge_memory都无实效,而且容易出现seg fault。
4. __gnu_cxx::__pool_alloc
http://www.verydemo.com/demo_c281_i22722.html
http://bbs.chinaunix.net/thread-1541961-1-1.html
有人引用c++标准程序库中一句话:
缺省配置器会执行内存分配和回收的一般性手法,也就是呼叫new和delete操作符。但是
c++并没有对于在什么时候以什么方式调用这些操作符给与明确规定。
对allocator来说,确实标准没有规定它调用operator new, operator delete, 或者是
其他分配函数的时机。但是,当vector和string被析构的时候,标准是有规定的,必须
调用get_allocator().deallocate.
总之如果采用了非vector/string的数据结构,应该没有办法写出通用的allocator来将
已经正确"释放"的内存"返回"给OS,除非连malloc/free等都重写。
另外,swap做法也只适用于vector/string;刚发现现在std::vector似乎都有一个
shrink_to_fit成员函数了,应该可以取代这个swap做法。

【在 c****e 的大作中提到】
: should be. Search to find an example.
y**b
发帖数: 10166
10
看来这个理解是对的,至少是经验之谈。
实际上我将unordered_set全都替换成vector,在损失功能情况下测试,发现内存消耗
几乎不变。可见问题不在于我使用了那种数据结构,而是这些数据serialized之后通过
mpi传输的时候,mpi底层实现要消耗大量内存。mpi有些参数可以调整内存消耗,但也
非常有限。
当然我还有其他解决办法,就是采用并行数据输出,整个并行计算结束之后用另外的程
序来合并数据、清楚冗余数据,免得干扰并行计算本身。

【在 n******t 的大作中提到】
: 都要这么搞了,用C好了。
: stl就是个让你别惹事好好用的东西。
:
: 存:

相关主题
vector的析构问题why do we still use dynamic allocation?
bad_alloc 问题什么是OS Memory management and heap structure?
"brk()" 和 mmap() 有什么区别? (转载)c+= 怎么实现 hashtable 的?
t****t
发帖数: 6806
11
你这里混淆了两个概念(在你bytes.com的link里有人已经提到了): 堆内存的分配/释放
, 即new/delete, 和进程内存的分配/释放, 即brk, 是两个不同的概念. 用ps/top看到
的是第二种, 但STL能控制的基本上是第一种.
先说STL的容器. clear当然不能保证释放, 但是析构函数一定会保证. 所以你如果不能
确定swap()能不能work, 不妨重新分配容器. 性能应该比swap高, 但是你反正是试一下
, 不用太担心.
再说OS. 在linux上, 缺省的glibc的分配模式是, 对于小内存块, 针对不同的尺寸, 有
不同的内存池. 对于大内存块, 是用mmap直接从系统要的. 对于内存池的delete, 就还
给内存池了, OS仍然看不到. 对于mmap的delete, 直接还给OS. 从一方面, 这可以解释
为什么vector是能"完全"释放, 因为vector的内存一定是连续的, 你开一个大vector肯
定是用mmap直接拿的, 删除之后就没了. 对于unordered_set, 内存不连续, 是渐渐分配
的, 很多删除之后还给内存池了, 所以你看到还不回去, 其实不是这么回事. 你可以试
一下弄一个vector慢慢插入元素, 我估计开始的小内存是不会还回去的.
至于你内存不够crash, 我估计是碎片太多造成堆分配困难. 这个解决的办法因问题而异
, 没有一个简单的答案. 所以你得自己想办法.

【在 y**b 的大作中提到】
: 折腾了几天,感觉这个问题可能无解,也许C++标准就不认为这是个问题。
: 先后测试了四种allocator,没有一个能生效,这里也有人提到:
: http://bytes.com/topic/c/answers/133169-return-memory-os
: 1. new/delete:
: http://www.josuttis.com/cppcode/allocator.html
: 2. malloc/free (跟1类似):
: http://www.usidcbbs.com/read-htm-tid-4896-fpage-3.html
: 3. boost::pool_allocator, boost::fast_pool_allocator:
: http://www.boost.org/doc/libs/1_53_0/libs/pool/doc/html/boost_p
: rfaces.html#boost_pool.pool.interfaces.interfaces.pool_allocator

c****e
发帖数: 1453
12
对于什么时候调用deallocate,你自己的allocator里面可以in
strument,看看具体是怎么回事情。
thrust所得也很有道理,系统显示不一定是你的内存用量。Windows下面
的workingset就是类似的概念。主要是OS这一层要有自己的空间优化。

【在 y**b 的大作中提到】
: 折腾了几天,感觉这个问题可能无解,也许C++标准就不认为这是个问题。
: 先后测试了四种allocator,没有一个能生效,这里也有人提到:
: http://bytes.com/topic/c/answers/133169-return-memory-os
: 1. new/delete:
: http://www.josuttis.com/cppcode/allocator.html
: 2. malloc/free (跟1类似):
: http://www.usidcbbs.com/read-htm-tid-4896-fpage-3.html
: 3. boost::pool_allocator, boost::fast_pool_allocator:
: http://www.boost.org/doc/libs/1_53_0/libs/pool/doc/html/boost_p
: rfaces.html#boost_pool.pool.interfaces.interfaces.pool_allocator

y**b
发帖数: 10166
13
是的,是两个层次的问题,stl和os两个层次,bytes.com里面说得很清楚。
内存碎片这个问题确实有些麻烦,而且不止是stl的内存碎片(这个尽量使用vector来消
除),
mpi从大量进程接收数据,也会造成无数内存碎片。
我测试了一下,mpi从10个进程接收数据,一共接收8MB数据,这样反复循环几次,接收
进程
内存消耗很快就达到100MB,数据结构全部使用vector。

【在 t****t 的大作中提到】
: 你这里混淆了两个概念(在你bytes.com的link里有人已经提到了): 堆内存的分配/释放
: , 即new/delete, 和进程内存的分配/释放, 即brk, 是两个不同的概念. 用ps/top看到
: 的是第二种, 但STL能控制的基本上是第一种.
: 先说STL的容器. clear当然不能保证释放, 但是析构函数一定会保证. 所以你如果不能
: 确定swap()能不能work, 不妨重新分配容器. 性能应该比swap高, 但是你反正是试一下
: , 不用太担心.
: 再说OS. 在linux上, 缺省的glibc的分配模式是, 对于小内存块, 针对不同的尺寸, 有
: 不同的内存池. 对于大内存块, 是用mmap直接从系统要的. 对于内存池的delete, 就还
: 给内存池了, OS仍然看不到. 对于mmap的delete, 直接还给OS. 从一方面, 这可以解释
: 为什么vector是能"完全"释放, 因为vector的内存一定是连续的, 你开一个大vector肯

t****t
发帖数: 6806
14
你需要改变一下内存分配的模式. 内存足够的时候, 用缺省的内存分配就够了. 但是如
果很紧张的话, 就需要定制了. 先看看malloc的option能不能解决(mallopt(3)), 如果
不行, 再自己做内存池.

【在 y**b 的大作中提到】
: 是的,是两个层次的问题,stl和os两个层次,bytes.com里面说得很清楚。
: 内存碎片这个问题确实有些麻烦,而且不止是stl的内存碎片(这个尽量使用vector来消
: 除),
: mpi从大量进程接收数据,也会造成无数内存碎片。
: 我测试了一下,mpi从10个进程接收数据,一共接收8MB数据,这样反复循环几次,接收
: 进程
: 内存消耗很快就达到100MB,数据结构全部使用vector。

y**b
发帖数: 10166
15
找到一篇谈内存碎片的:
http://blog.163.com/[email protected]/blog/static/8702267200971894
里面提到内存碎片的罪魁祸首并不是libstdc++的的STL,而是glibc的malloc。
把那个例子换成std::vector,然后new一个对象就插入一个,同样会产生内存碎片。
如果外面加个大循环,乖乖不得了,几下子就能崩溃。
但是如果只产生临时对象,将临时对象的拷贝一个一个插入vector,每次大循环之前
用clear清空vector,不会耗光内存。我的程序是这样。
但主要问题还是在于mpi本身的缓存:
unordered_set单进程计算反复循环,内存不增加;mpi并行计算反复循环,内存增加。
vector单进程计算反复循环,内存不增加;mpi并行计算反复循环,内存增加。

【在 t****t 的大作中提到】
: 你需要改变一下内存分配的模式. 内存足够的时候, 用缺省的内存分配就够了. 但是如
: 果很紧张的话, 就需要定制了. 先看看malloc的option能不能解决(mallopt(3)), 如果
: 不行, 再自己做内存池.

t****t
发帖数: 6806
16
STL会调用malloc的, 没区别. 你要看到底层的东西.

【在 y**b 的大作中提到】
: 找到一篇谈内存碎片的:
: http://blog.163.com/[email protected]/blog/static/8702267200971894
: 里面提到内存碎片的罪魁祸首并不是libstdc++的的STL,而是glibc的malloc。
: 把那个例子换成std::vector,然后new一个对象就插入一个,同样会产生内存碎片。
: 如果外面加个大循环,乖乖不得了,几下子就能崩溃。
: 但是如果只产生临时对象,将临时对象的拷贝一个一个插入vector,每次大循环之前
: 用clear清空vector,不会耗光内存。我的程序是这样。
: 但主要问题还是在于mpi本身的缓存:
: unordered_set单进程计算反复循环,内存不增加;mpi并行计算反复循环,内存增加。
: vector单进程计算反复循环,内存不增加;mpi并行计算反复循环,内存增加。

1 (共1页)
相关主题
请问关于 share memory 的问题STL/vector引用成员变量。
程序占用很大内存vector的析构问题
怎样高效管理内存?bad_alloc 问题
C++中释放的内存可能立即返回系统吗?"brk()" 和 mmap() 有什么区别? (转载)
突然发现现在很反感malloc了why do we still use dynamic allocation?
寻找一个allocator 做一个指定内存空间内的 alloc/free什么是OS Memory management and heap structure?
请教关于C++内存管理c+= 怎么实现 hashtable 的?
STL vector的clear如何强制归还系统?请问用mmap分配的共享内存如何回收?
相关话题的讨论汇总
话题: 内存话题: 释放话题: std话题: vector话题: swap