Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 运行函数后强制释放内存_Python_Python 3.x - Fatal编程技术网

Python 运行函数后强制释放内存

Python 运行函数后强制释放内存,python,python-3.x,Python,Python 3.x,我使用一个模块(我不能修改),其中包含我需要使用的方法。此方法返回10GB的数据,但也分配8GB的内存,而不会释放这些内存。我需要在长时间运行的脚本开始时使用此方法,并且我希望确保在运行该方法后释放8GB内存。我的选择是什么 需要明确的是,8GB不会被脚本重用,也就是说,如果我在运行该方法后创建了一个大的numpy数组,那么会为该numpy数组分配额外的内存 我曾考虑过使用多处理模块在单独的进程中运行该方法(并返回结果),但在序列化该方法的大结果时遇到问题-默认pickler无法对10GB进行p

我使用一个模块(我不能修改),其中包含我需要使用的方法。此方法返回10GB的数据,但也分配8GB的内存,而不会释放这些内存。我需要在长时间运行的脚本开始时使用此方法,并且我希望确保在运行该方法后释放8GB内存。我的选择是什么

需要明确的是,8GB不会被脚本重用,也就是说,如果我在运行该方法后创建了一个大的numpy数组,那么会为该numpy数组分配额外的内存

我曾考虑过使用多处理模块在单独的进程中运行该方法(并返回结果),但在序列化该方法的大结果时遇到问题-默认pickler无法对10GB进行pickle,即使我强制多处理使用pickle version 4,pickling也会有非常大的内存开销。如果不能修改有问题的模块,我还能做什么

编辑:下面是一个例子

from dataloader import dataloader1
result = dataloader1.get("DATA1")

我理解,DATALADADER是Python包装,使用PybDun11围绕一些C++代码。我对它的内部运作知之甚少。上面的代码导致使用18GB。如果我跑了

del result
10GB被正确释放,但8GB仍在继续使用(似乎不再存在python对象)


Edit2:如果我创建一个较小的numpy阵列(例如3GB),内存使用量将保持在8GB。如果我删除它并创建一个6GB的numpy阵列,内存使用量会变为14GB,删除后又会变为8GB。我仍然需要发布到操作系统中的8GB。Python使用两种不同的机制来释放内存

  • 它主要使用并在不再需要时释放内存(例如,对象从作用域中丢失)

  • ,它是次要的,用于收集具有循环引用的对象(
    a->b->c->a
    )。这可以使用一个按钮触发。否则,Python将自行决定何时释放内存


  • 但是,我强烈建议对代码进行分析和更改,这样就不会占用太多内存。可以查看流,或者使用数据库。

    您可以修改该函数吗?
    如果内存由某个模块持有,请尝试重新加载该模块(importlib.reload),该模块将释放内存。

    如果内存不是由gc释放的,则可能是因为创建它的类中存储了一个对象,因此可以选择(通过分析)查找类中的这个大属性是什么实例,并将其分配给
    None
    ,这可能会导致gc释放内存。

    您是否尝试过内存分析以查看内存中的实际内容?您可以尝试以另一种方式(如JSON)序列化10GB数据。您真的需要内存中的所有数据吗?因为也许你可以通过延迟加载来解决问题,而不是一次转储所有内容…@norok2查看我的编辑。我该如何分析这一点?如果我的理解是正确的,内存被底层C++代码分配,并且永远不会释放。如果分配是由C扩展而从不释放的,那么它就是库的内存泄漏或不完整的API(缺少‘清除’方法)。不管怎样,这都是一个错误,应该报告。重新加载模块似乎没有帮助。不能重新加载C扩展