如何在 Python 中明确释放内存?

2024-11-26 08:37:00
admin
原创
169
摘要:问题描述:我编写了一个 Python 程序,它对大型输入文件进行操作,以创建几百万个表示三角形的对象。该算法如下:读取输入文件处理文件并创建一个三角形列表,以它们的顶点表示以 OFF 格式输出顶点:顶点列表后跟三角形列表。三角形由顶点列表中的索引表示OFF 要求我在打印三角形之前先打印出完整的顶点列表,这意味...

问题描述:

我编写了一个 Python 程序,它对大型输入文件进行操作,以创建几百万个表示三角形的对象。该算法如下:

  1. 读取输入文件

  2. 处理文件并创建一个三角形列表,以它们的顶点表示

  3. 以 OFF 格式输出顶点:顶点列表后跟三角形列表。三角形由顶点列表中的索引表示

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

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


解决方案 1:

根据Python 官方文档,你可以使用 明确调用垃圾收集器来释放未引用的内存gc.collect()。例如:

import gc

gc.collect()

您应该在标记要丢弃的内容后执行此操作del

del my_array
del my_object
gc.collect()

解决方案 2:

不幸的是(取决于您的 Python 版本和发行版),某些类型的对象使用“空闲列表”,这是一种巧妙的局部优化,但可能会导致内存碎片,具体来说,通过使越来越多的内存“指定”用于仅特定类型的对象,从而无法用于“一般基金”。

确保大量但临时的内存使用在完成后确实将所有资源返回给系统的唯一真正可靠的方法是让该使用发生在子进程中,该子进程执行内存密集型工作然后终止。在这种情况下,操作系统将完成其工作,并乐意回收子进程可能已占用的所有资源。幸运的是,该multiprocessing模块使这种操作(过去相当麻烦)在现代版本的 Python 中变得不那么糟糕。

在您的用例中,子流程积累一些结果并确保这些结果可供主流程使用的最佳方式似乎是使用半临时文件(半临时的意思是,不是关闭时自动消失的那种文件,只是在您完成所有操作后明确删除的普通文件)。

解决方案 3:

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

我听说人们在 Linux 和 Unix 类型的系统上分叉一个 python 进程来做一些工作,获得结果然后杀死它。

这篇文章对 Python 垃圾收集器进行了说明,但我认为缺乏内存控制是托管内存的缺点

解决方案 4:

Python 具有垃圾收集功能,因此如果你减少列表的大小,它将回收内存。你也可以使用“del”语句完全删除变量:

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

解决方案 5:

del可以成为你的朋友,因为当没有其他引用它们时,它会将对象标记为可删除。现在,CPython 解释器通常会保留这块内存以供以后使用,因此你的操作系统可能看不到“释放的”内存。)

也许您一开始就不会遇到任何内存问题,因为您使用的数据结构更紧凑。因此,数字列表的内存效率远低于标准array模块或第三方numpy模块使用的格式。您可以将顶点放在 NumPy 3xN 数组中,将三角形放在 N 元素数组中,这样可以节省内存。

解决方案 6:

您无法明确释放内存。您需要做的是确保不保留对对象的引用。然后它们将被垃圾收集,从而释放内存。

就你的情况而言,当你需要大型列表时,你通常需要重新组织代码,通常使用生成器/迭代器。这样,你根本不需要在内存中保存大型列表。

解决方案 7:

我在从文件中读取图形时遇到了类似的问题。处理包括计算 200 000x200 000 浮点矩阵(一次一行),该矩阵无法放入内存。尝试在计算之间释放内存,解决了与gc.collect()内存相关的问题,但导致了性能问题:我不知道为什么,但即使使用的内存量保持不变,每次新的调用gc.collect()都比前一次花费更多时间。因此,垃圾收集很快就占用了大部分计算时间。

为了解决内存和性能问题,我改用了曾经在某处读到过的一个多线程技巧(抱歉,我再也找不到相关的帖子了)。以前,我会在一个大for循环中读取文件的每一行,然后处理它,并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

解决方案 8:

正如其他答案已经提到的,即使 Python 代码不再使用内存(因此gc.collect()不会释放任何内容),Python 也可以阻止将内存释放给操作系统,尤其是在长时间运行的程序中。无论如何,如果您使用的是 Linux,您可以尝试通过直接调用 libc 函数malloc_trim(手册页)来释放内存。类似:

import ctypes
libc = ctypes.CDLL("libc.so.6")
libc.malloc_trim(0)

解决方案 9:

其他人已经发布了一些方法,您可能能够“诱导”Python 解释器释放内存(或以其他方式避免出现内存问题)。您可能应该先尝试一下他们的想法。但是,我觉得直接回答您的问题很重要。

实际上没有任何方法可以直接告诉 Python 释放内存。事实上,如果您想要如此低级别的控制,您将不得不用 C 或 C++ 编写扩展。

话虽如此,还是有一些工具可以帮助解决这个问题:

  • 赛通

  • 痛饮

  • 提升python

解决方案 10:

如果您不关心顶点重用,则可以有两个输出文件——一个用于顶点,一个用于三角形。完成后,将三角形文件附加到顶点文件。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1041  
  IPD(Integrated Product Development,集成产品开发)是一种系统化的产品开发方法论,旨在通过跨职能团队的协作,优化产品开发的效率和质量。IPD流程强调从市场需求出发,通过并行工程、跨部门协作和阶段性评审,确保产品从概念到上市的每个环节都高效且可控。随着敏捷开发方法的普及,越来越多的企业开始...
华为IPD流程   34  
  随着企业产品开发复杂度的提升以及市场需求的快速变化,传统的产品开发模式逐渐显现出局限性。集成产品开发(IPD)流程与敏捷开发(Agile Development)作为两种主流的开发方法论,分别从系统化管理和快速响应需求的角度为企业提供了解决方案。然而,单独使用其中一种方法往往无法完全满足企业在效率、质量和创新上的多重需...
华为IPD流程   31  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司成功的关键因素之一。它不仅帮助华为在技术上实现了快速创新,还通过市场导向确保了产品的商业成功。IPD流程通过整合技术与市场双驱动,实现了从需求定义到产品交付的全生命周期管理。这种模式不仅提高了产品的开发效率,还降低了市...
IPD流程中PDCP是什么意思   23  
  在研发领域,集成产品开发(IPD)流程已经成为企业提升创新效率和市场竞争力的重要手段。然而,资源分配的不合理往往是制约IPD流程效率的关键因素之一。无论是人力资源、财务资源还是技术资源,如何高效分配直接关系到项目的成功与否。优化资源分配不仅能够缩短产品开发周期,还能降低研发成本,提升产品的市场竞争力。因此,掌握资源分配...
IPD流程中CDCP   26  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用