这是一部分代码,全部代码的话太长了。
def main(rg1,rg2):
global Abins
Abins=[[[] for x in range(50)] for y in range(50)]
for ra in range(rg1,rg2):
for dec in range(180):
print ra, dec
if file_list[ra][dec] == []:
continue
else:
print len(file_list[ra][dec])
for b in file_list[ra][dec]:
for bins_ra in range(-4,5):
for bins_dec in range(-4,5):
for a in file_list[ra+bins_ra][dec+bins_dec]:
if a[4]<b[4]:
calcute(str(a[0]),str(b[0]),a[3],b[3],a[1],b[1],a[2],b[2])
print("start print")
for i in range(FenShu):
for j in range(FenShu):
file_save=open('./Abins_'+str(rg1)+'_'+str(rg2)+'_'+str(i)+'_'+str(j), 'w')
file_save.write(json.dumps(Abins[i][j]))
file_save.close()
del Abins
gc.collect()
for ra in range(80,140):
main(ra,ra+10)
这段代码的意思是,我每做一次 main 这个函数,都会往全局变量 Abins 数组中添加一些数据,由于全部做完之后这个数组会太大(远超过物理内存),所以每一次循环都输出一个文件。
但我的意图是输出完这个文件之后应该就释放了原来的 Abins 专用的内存了,不知道为什么执行的时候还是占用很多很多内存。 是做天文数据处理用的。 多谢!
1
justfly 2016-03-22 20:48:57 +08:00
一个 python 进程内存的占用是这个进程运行中峰值的内存占用。
python 会把回收的内存放到自己的空闲链表中,并不是还给操作系统。 |
2
yanyuechuixue OP @justfly 这样的话还是会跑着跑着内存占用 100%,然后跑不动了啊。。
有什么办法可以把内存占用降下来么? |
3
yanyuechuixue OP @justfly 就是,当内存占用百分之九十多的时候, CPU 占用率就只有百分之四、五, 而不是百分之百了……所以我认为是跑不动了。
|
4
justfly 2016-03-22 21:04:49 +08:00
函数里面的变量没必要 global 。 先看看你一次 main 占多少内存吧。把 for 去掉 只跑一次 main 然后用 sleep block 住看内存。
|
5
northisland 2016-03-22 21:07:02 +08:00 1
del Abins
这句放在 2 重循环外边了吧~~ 读完所有文件再释放? |
6
yanyuechuixue OP @justfly 因为如果不 global 的话,在这个函数调用的另一个子函数就没法往 Abins 里填充元素……
|
7
yanyuechuixue OP @northisland 嗯,执行完 main()之后再释放,下一次执行 main()再创建。
|
8
dreampuf 2016-03-22 21:24:20 +08:00 1
CPython 不会将内存释放给操作系统。 GC 只会将对象回收到 runtime 的 free list 中,以备再用。
解决方案简单粗暴就用子进程进行数据处理,然后将结果传递给父进程。 |
9
yanyuechuixue OP @dreampuf 好的,谢谢,我试一下。
麻烦问一下,如果传递一个很大的数组的话,会不会速度会很慢? |
10
dreampuf 2016-03-22 21:34:33 +08:00
如何传递?跨进程 /线程,还是同上下文只是函数调用?
建议 Google 一下,这些都是书本上的知识了 |
11
cphilo 2016-03-22 21:36:25 +08:00
考虑使用类似 xrange 这种迭代器
|
12
cphilo 2016-03-22 21:38:17 +08:00
应该是生成器,不是迭代器, v2 不能删除评论
|
13
sujin190 2016-03-22 21:42:28 +08:00
@dreampuf free list 不是有长度限制的么?超过了依然会释放的,不过会有整数缓存,字符串缓存什么的,如果你从 i 循环到数百万,内存占用数百 M 是正常的
|
14
mko0okmko0 2016-03-22 22:15:50 +08:00
PYPY 能好一点吗?我不知道等楼下回答.
我个人会推荐换用 JAVA 或其他语言来解决脚本语言的性能或是回收问题. 我帮你找的方法: http://f.dataguru.cn/thread-296696-1-1.html 个人觉得 C#(mono)很棒(有 SIMD 加速),JAVA 次之(有 SSE/AVX 加速但要加参数) |
15
dreampuf 2016-03-22 22:30:25 +08:00
|
16
sujin190 2016-03-23 13:21:21 +08:00
@dreampuf 是的,一般不开启,但看这个逻辑似乎是每次最小分配 16*256KB 字节,再分成 256KB 大小的每块,再在每块上分配对象需要的内存,但一块上所有对象都被释放的话,该块还是会被释放的
|
18
sujin190 2016-03-23 20:41:06 +08:00
@dreampuf https://github.com/python/cpython/blob/master/Objects/obmalloc.c#L1598
而且内存限制也不是说不能超过这个内存,而是当内存超过这个值之后直接由 c 的 malloc 直接来分配,所以如果你有引用没有释放,内存依然还是会占用很高的 |
19
billgreen1 2016-03-24 00:10:51 +08:00
强烈建议你重构代码,六个 for 循环,我从来没见到过这么多的循环嵌套的。
|
20
yanyuechuixue OP @billgreen1 我也没见过……这个已经没办法的事情了……这是我能想到的最节约时间数据结构决定的……
是把整个天空分成 180*360 个格子,每个里面放了好多个数组,对每个数组都要与周围的 64 个格子里的其他数组进行运算,这个运算包含两个循环……………… |
21
billgreen1 2016-03-25 21:03:45 +08:00
@yanyuechuixue
那就拆分,用 generator 。 假设天空 180*360 的格子 命名为 grids. paired_array = ( (array1, array2) for array1 in grid for array2 in neighbor for neighbor in get_neighbors(grid) for grid in grids ) result = [calculate(array1, array2) for array1, array2 in paired_array] |
22
billgreen1 2016-03-25 21:06:18 +08:00
我猜你的 calculate 运算时对称的, calculate(x,y) 等于 calculate(y,x)
你可以试试 lru.cache 来节约运算时间。 |