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

2024-11-26 08:37:00
admin
原创
257
摘要:问题描述:我编写了一个 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:

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

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用