gpt4 book ai didi

python - 在 python 中调用函数后不会释放内存

转载 作者:行者123 更新时间:2023-12-04 17:54:13 25 4
gpt4 key购买 nike

我使用 memory_profiler 已经有一段时间了,从下面的小程序中得到了这个有趣但令人困惑的结果:

import pandas as pd
import numpy as np

@profile
def f(p):
tmp = []
for _, frame in p.iteritems():
tmp.append([list(record) for record in frame.to_records(index=False)])

# initialize a list of pandas panels
lp = []
for j in xrange(50):
d = {}
for i in xrange(50):
df = pd.DataFrame(np.random.randn(200, 50))
d[i] = df
lp.append(pd.Panel(d))

# execution (iteration)
for panel in lp:
f(panel)

然后如果我使用 memory_profiler 的 mprof 来分析运行时的内存使用情况,mprof run test.py 没有任何其他参数,我得到这个: memory_profiling_results_1.png .

每次函数调用 f() 后似乎有未释放的内存。

tmp 只是一个本地列表,每次调用 f() 时都应该重新分配和重新分配内存。显然,所附图表中存在一些差异。我知道 python 有自己的内存管理 block ,还有 int 和其他类型的空闲列表,gc.collect() 应该可以发挥作用。事实证明,显式 gc.collect() 不起作用。 (也许是因为我们正在处理 pandas 对象、面板和框架?我不知道。)

最令人困惑的部分是,我没有更改或修改f() 中的任何变量。它所做的只是将一些列表表示副本放入本地列表中。因此 python 不需要复制任何东西。那么为什么以及如何发生这种情况呢?

=================

一些其他观察:

1) 如果我用 f(panel.copy()) (最后一行代码)调用 f(),则传递副本而不是原始对象引用,我有一个完全不同的内存使用结果:memory_profiling_results_2.png . python 是否聪明地告诉这个传递的值是一个副本,以便它可以在每次函数调用后执行一些内部技巧来释放内存?

2) 我认为这可能是因为df.to_records()。好吧,如果我将它更改为 frame.values,我会得到类似的平坦内存曲线,就像上面显示的 memory_profiling_results_2.png 一样,在迭代期间(虽然我确实需要 to_records() 因为它维护了列数据类型,而 .values 将数据类型搞乱了)。但我研究了 frame.py 在 to_records() 上的实现。我不明白为什么它会占用内存,而 .values 却可以正常工作。

我在 Windows 上运行该程序,使用 python 2.7.8、memory_profiler 0.43 和 psutil 5.0.1。

最佳答案

这不是内存泄漏。您看到的是 pandas.core.NDFrame 缓存一些结果的副作用。这允许它在您第二次请求时返回相同的信息,而无需再次运行计算。将示例代码的末尾更改为类似于以下代码并运行它。你应该会发现第二次通过内存增加不会发生,而且执行时间会更少。

import time

# execution (iteration)
start_time = time.time()
for panel in lp:
f(panel)
print(time.time() - start_time)

print('-------------------------------------')
start_time = time.time()
for panel in lp:
f(panel)
print(time.time() - start_time)

关于python - 在 python 中调用函数后不会释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41754072/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com