我如何显式释放Python中的内存?

我写了一个Python程序,在一个大的input文件上作用来创build几百万个代表三angular形的对象。 该algorithm是:

  1. 读取input文件
  2. 处理文件并创build一个三angular形列表,由它们的顶点表示
  3. 以OFF格式输出顶点:顶点列表,后跟一列三angular形。 三angular形由顶点列表中的索引表示

在打印出三angular形之前打印出完整的顶点列表的OFF的要求意味着在将输出写入文件之前,我必须在内存中保存三angular形的列表。 与此同时,由于列表的大小,我得到内存错误。

告诉Python我不再需要某些数据,并且它可以被释放的最好方法是什么?

根据Python官方文档 ,你可以强制垃圾收集器释放未被引用的内存与gc.collect()

不幸的是(取决于你的版本和Python的版本),某些types的对象使用“空闲列表”,这是一个整洁的本地优化,但可能会导致内存碎片,特别是通过使更多和更多的内存“专用”从而无法获得“普通基金”。

唯一真正可靠的方法是确保大量但暂时使用的内存DOES在完成时将所有资源都返回给系统,这是为了在subprocess中发生这种使用,这样内存耗尽的工作就会终止。 在这种情况下,操作系统将会完成它的工作,并乐意回收subprocess可能吞噬的所有资源。 幸运的是,在现代版本的Python中, multiprocessing模块使得这种操作(过去相当痛苦)不算太坏。

在你的用例中,似乎子过程积累一些结果并确保这些结果可用于主进程的最好方法是使用半临时文件(通过半临时文件,我的意思是,不是那种types的文件在closures时会自动消失,只有当你完成所有的时候才显式删除的普通文件)。

del语句可能是有用的,但是IIRC 不保证释放内存 。 文档在这里 …而这是为什么它没有发布在这里 。

我已经听说Linux和Unixtypes系统中的人员正在分派一个python进程来完成一些工作,获得结果然后将其杀死。

本文对Python垃圾收集器有logging,但我认为缺乏内存控制是pipe理内存的缺点

Python是垃圾收集的,所以如果你减less列表的大小,它会回收内存。 你也可以使用“del”语句完全去掉一个variables:

 biglist = [blah,blah,blah] #... del biglist 

你不能明确地释放内存。 你需要做的是确保你不保留对象的引用。 他们将被垃圾收集,释放内存。

在你的情况下,当你需要大的列表,你通常需要重新组织代码,通常使用生成器/迭代器。 这样你就不需要在内存中拥有大的列表。

http://www.prasannatech.net/2009/07/introduction-python-generators.html

(释放内存是自动定期完成的,因此del可以是你的朋友,因为它将对象标记为可删除。)

也许你不会遇到任何内存问题,首先通过使用更紧凑的数据结构。 因此,数字列表比标准array模块或第三方numpy模块使用的格式less得多的内存效率。 通过将顶点放在NumPy 3xN数组中,并将三angular形放在N元素数组中,可以节省内存。

其他人已经发布了一些方法,你可以“哄骗”Python解释器来释放内存(或者避免有内存问题)。 有机会,你应该先尝试一下他们的想法。 但是,我觉得给你一个直接的答案是很重要的。

没有任何方法可以直接告诉Python释放内存。 这件事情的事实是,如果你想要一个低水平的控制,你将不得不写在C或C + +的扩展。

也就是说,有一些工具可以帮助解决这个问题:

  • 用Cython
  • 痛饮
  • 增强python

如果你不关心顶点重用,你可以有两个输出文件 – 一个用于顶点,一个用于三angular形。 然后在完成时将三angular形文件附加到顶点文件。

从文件读取graphics时遇到类似的问题。 处理包括计算200 000×200 000个浮点matrix(一次一行),这些matrix不适合记忆。 试图使用gc.collect()解决计算之间的内存问题,修复了与内存相关的问题,但是却导致了性能问题:我不知道为什么,但即使使用的内存量保持不变,每次新的调用gc.collect()花了比前一个更多的时间。 所以很快的垃圾收集花费了大部分的计算时间。

为了解决内存和性能问题,我转向使用multithreading技巧,我在某处读了一次(对不起,我找不到相关的post了)。 在我阅读大循环中的每一行文件之前,处理它,并且每隔一段时间运行gc.collect()来释放内存空间。 现在我调用一个函数来读取和处理一个新线程中的一个文件块。 一旦线程结束,内存将自动释放,而不会出现奇怪的性能问题。

实际上它是这样的:

 from dask import delayed // this module wraps the multithreading def f(storage, index, chunk_size): // the processing function // read the chunk of size chunk_size starting at index in the file // process it using data in storage if needed // append data needed for further computations to storage return storage partial_result = delayed([]) // put into the delayed() the constructor for your data structure // i personally use "delayed(nx.Graph())" since I am creating a networkx Graph chunk_size = 100 // ideally you want this as big as possible while still enabling the computations to fit in memory for index in range(0, len(file), chunk_size): // we indicates to dask that we will want to apply f to the parameters partial_result, index, chunk_size partial_result = delayed(f)(partial_result, index, chunk_size) // no computations are done yet ! // dask will spawn a thread to run f(partial_result, index, chunk_size) once we call partial_result.compute() // passing the previous "partial_result" variable in the parameters assures a chunk will only be processed after the previous one is done // it also allows you to use the results of the processing of the previous chunks in the file if needed // this launches all the computations result = partial_result.compute() // one thread is spawned for each "delayed" one at a time to compute its result // dask then closes the tread, which solves the memory freeing issue // the strange performance issue with gc.collect() is also avoided