我使用内部Python库进行科学计算。我需要连续复制一个对象,修改它,然后删除它。对象很大,导致我的机器在几个周期后耗尽内存。
第一个问题是我使用python' del
来删除对象,这显然只取消引用对象,而不是释放RAM。
第二个问题是即使我将整个进程封装在一个函数中,在调用该函数之后,RAM仍然没有被释放。这是一个代码片段,可以更好地解释这个问题。
ws = op.core.Workspace()
net = op.network.Cubic(shape=[100,100,100], spacing=1e-6)
proj = net.project
def f():
for i in range(5):
clone = ws.copy_project(proj)
result = do_something_with(clone)
del clone
f()
gc.collect()
>>> ws
{'sim_01': [<openpnm.network.Cubic object at 0x7fed1c417780>],
'sim_02': [<openpnm.network.Cubic object at 0x7fed1c417888>],
'sim_03': [<openpnm.network.Cubic object at 0x7fed1c417938>],
'sim_04': [<openpnm.network.Cubic object at 0x7fed1c417990>],
'sim_05': [<openpnm.network.Cubic object at 0x7fed1c4179e8>],
'sim_06': [<openpnm.network.Cubic object at 0x7fed1c417a40>]}
我的问题是如何完全删除Python对象?
谢谢!
PS。在代码段中,每次调用ws.copy_project
时,proj
的副本都会存储在ws
字典中。
答案 0 :(得分:0)
这里有一些非常聪明的蟒蛇人。他们可能会告诉你更好的方法来保持你的记忆清晰,但我之前使用过漏洞库,并找到一种(迄今为止)万无一失的方法来保证你的内存在使用后被清除:在另一个进程中执行内存占用
要做到这一点,您需要安排一种简单的方法,使您的长计算可以单独执行。我通过在我现有的python脚本中添加特殊标志来完成此操作,该脚本告诉它只是运行该函数;您可能会发现将该函数放在单独的.py文件中更容易,例如:
import sys
def do_something_with(i)
# Your example is still too vague. Clearly, something differentiates
# each do_something_with, otherwise you're just taking the
# same inputs 5 times over.
# Whatever the difference is, pass it in as an argument to the function
ws = op.core.Workspace()
net = op.network.Cubic(shape=[100,100,100], spacing=1e-6)
proj = net.project
# You may not even need to clone anymore?
clone = ws.copy_project(proj)
result = do_something_with(clone)
# Whatever arg(s) you need to get to the function, just pass it in on the command line
if __name__ == "__main__":
sys.exit(do_something_with(sys.args[1:]))
您可以使用任何处理子进程的python工具来执行此操作。在python 3.5+中,推荐的方法是subprocess.run。您可以将更大的功能更改为以下内容:
import subprocess
invoke_do_something(i):
completed_args = subprocess.run(["python", "do_something_with.py", str(i)], check=False)
return completed_args.returncode
results = map(invoke_do_something, range(5))
你显然需要根据自己的情况定制它,但是通过在子进程中运行,你可以保证不必担心内存被清理。作为额外的好处,您可以使用multiprocess.Pool.map一次使用多个处理器。 (我故意将其编码为使用map来简化这样的转换。如果您愿意,您仍然可以使用for循环,然后您不需要invoke...
函数。)多处理可以加快处理速度,但是因为你已经担心内存,几乎肯定是一个坏主意 - 有了大量内存占用的多个进程,你的系统本身可能会很快耗尽内存并终止你的进程。
你的例子相当模糊,所以我写的很高。如果你需要,我可以回答一些问题。