我如何使用子进程强制python释放内存?

Noo*_*bot 22 python subprocess memory-management python-2.7

我正在阅读Python内存管理,并希望减少我的应用程序的内存占用.有人建议,子程序在减轻问题方面会有很长的路要走; 但我无法概念化需要做什么.有人可以提供一个简单的例子来说明如何...

def my_function():
    x = range(1000000)
    y = copy.deepcopy(x)
    del x
    return y

@subprocess_witchcraft
def my_function_dispatcher(*args):
    return my_function()
Run Code Online (Sandbox Code Playgroud)

...进入一个真正的子处理函数,不存储额外的"自由列表"?

奖金问题:

这个"自由列表"概念是否也适用于python c-extensions?

use*_*342 31

优化建议的重要一点是确保my_function()只在子进程中调用.该deepcopydel是无关的-一旦你创建的过程包含五个百万个不同整数,同时持有到所有的人,过来的游戏.即使你不再引用这些对象,Python也会通过在一个边界中保留对500万个空整数对象大小的字段的引用来释放它们,它们等待重用于下一个想要创建500万个整数的函数.这是另一个答案提到的免费列表,它购买了快速分配和重新分配整数和浮点数.对于Python来说,注意这不是内存泄漏是公平的,因为内存肯定可用于进一步分配.但是,在进程结束之前,该内存不会返回到系统,除了分配相同类型的数字之外,它也不会被重用.

大多数程序都没有这个问题,因为大多数程序都没有创建病态庞大的数字列表,释放它们,然后期望将这些内存重用于其他对象.使用numpy的程序也是安全的,因为numpy它以紧密打包的本机格式存储其数组的数字数据.对于遵循此使用模式的程序,缓解问题的方法是首先不要同时创建大量的整数,至少不要在需要将内存返回给系统的过程中.目前还不清楚你有什么确切的用例,但现实世界的解决方案可能需要的不仅仅是"魔术装饰".

这是子进程的来源:如果数字列表是在另一个进程中创建的,那么与该列表关联的所有内存(包括但不限于整数存储)都将被释放并仅通过终止操作返回给系统子流程.当然,您必须设计程序,以便可以在子系统中创建和处理列表,而无需传输所有这些数字.子进程可以接收创建数据集所需的信息,并且可以发回从处理列表获得的信息.

为了说明这个原理,让我们升级你的例子,以便整个列表实际上需要存在 - 比如说我们是对排序算法进行基准测试.我们想要创建一个庞大的整数列表,对它进行排序,并可靠地释放与列表相关的内存,以便下一个基准测试可以根据自己的需要分配内存,而不必担心RAM耗尽.要生成子进程并进行通信,这将使用以下multiprocessing模块:

# To run this, save it to a file that looks like a valid Python module, e.g.
# "foo.py" - multiprocessing requires being able to import the main module.
# Then run it with "python foo.py".

import multiprocessing, random, sys, os, time

def create_list(size):
    # utility function for clarity - runs in subprocess
    maxint = sys.maxint
    randrange = random.randrange
    return [randrange(maxint) for i in xrange(size)]

def run_test(state):
    # this function is run in a separate process
    size = state['list_size']
    print 'creating a list with %d random elements - this can take a while... ' % size,
    sys.stdout.flush()
    lst = create_list(size)
    print 'done'
    t0 = time.time()
    lst.sort()
    t1 = time.time()
    state['time'] = t1 - t0

if __name__ == '__main__':
    manager = multiprocessing.Manager()
    state = manager.dict(list_size=5*1000*1000)  # shared state
    p = multiprocessing.Process(target=run_test, args=(state,))
    p.start()
    p.join()
    print 'time to sort: %.3f' % state['time']
    print 'my PID is %d, sleeping for a minute...' % os.getpid()
    time.sleep(60)
    # at this point you can inspect the running process to see that it
    # does not consume excess memory
Run Code Online (Sandbox Code Playgroud)

奖金答案

由于问题不明确,很难提供奖金问题的答案."自由列表概念"就是一个概念,一个需要在常规Python分配器之上显式编码的实现策略.大多数Python类型使用该分配策略,例如,它不用于使用该class语句创建的类的实例.实施免费清单并不难,但它相当先进,很少在没有充分理由的情况下进行.如果一些扩展的作者已经选择使用它的类型之一空闲列表,可以预期的是,他们知道一个自由列表提供了权衡-在一些额外的空间成本获得额外的快速分配/释放(为空闲列表和空闲列表本身上的对象)以及无法将内存重用于其他内容.

  • 您能否确认这是否可以在 Windows 和 Linux 下运行,可以在哪些 Python 版本下运行,或者需要进行哪些必要的修改?我无法让它在 Windows 上的 Python 2.6.5 32 位中运行,目前没有时间尝试使用 Linux。 (2认同)
  • 我没有Windows来测试它,但如果你能告诉我你观察到的问题是什么(例外?没有输出?),我会尝试解决它.这个例子肯定是**用于跨平台的**. (2认同)
  • @ user4815162342:您可以通过设置[`multiprocessing.set_start_method('spawn')`](https://docs.python.org/3/library/multiprocessing.html#multiprocessing.set_start_method)进行测试来模拟Windows行为 (2认同)