【问题标题】:Python3 multiprocessing: Memory Allocation ErrorPython3 多处理:内存分配错误
【发布时间】:2023-04-10 19:54:01
【问题描述】:

我知道这个问题已经被问过很多次了,但答案并不适用。 这是 answer one 在 StackoverFlow 上使用多处理的并行循环:

import multiprocessing as mp

def processInput(i):
    return i * i

if __name__ == '__main__':
    inputs = range(1000000)
    pool = mp.Pool(processes=4)
    results = pool.map(processInput, inputs)
    print(results)

此代码运行良好。但是如果我将范围增加到 1000000000,我的 16GB 内存将被完全填满,我得到 [Errno 12] 无法分配内存map 函数似乎启动了尽可能多的进程。如何限制并行进程的数量?

【问题讨论】:

    标签: python-3.x python-multiprocessing


    【解决方案1】:

    pool.map 函数按照您的指示启动 4 个进程(在 processes=4 行中,您指示池可以使用多少个进程来执行您的逻辑)。

    但是,此实现存在一个不同的问题。 pool.map 函数将返回一个对象列表,在本例中是其编号。 数字不像 ANSI-C 中的 int-s 那样工作,它们有开销并且不会溢出(例如,在 32 位上达到 2^31+1 时转为 -2^31)。 此外,python 列表不是数组,确实会产生开销。

    更具体地说,在 python 3.6 上,运行以下代码会显示一些开销:

    >>>import sys
    >>>t = [1,2,3,4]
    >>>sys.getsizeof(t)
    96
    >>>t = [x for x in range(1000)]
    >>>sys.getsizeof(t)
    9024
    

    所以这意味着小列表中每个数字 24 个字节,大列表中大约 9 个字节。 所以对于 10^9 大小的列表,我们得到大约 8.5GB

    编辑:1. 正如 tfb 所提到的,这甚至不是底层 Number 对象的大小,只是指针和列表开销,这意味着我在原始答案中没有考虑更多的内存开销。

    1. windows上默认的python安装是32位(你可以得到64位安装,但是你需要查看python网站上所有可用下载的部分),所以我假设你使用的是32位安装。

    【讨论】:

    • 我很确定sys.getsizeof 只是告诉你数组对象的大小,而不是它的内容。例如1.0*sys.getsizeof([[i for i in xrange(10)] for j in xrange(10000)])/10000 在我的实现中大约是 8.7。很明显,它不计算数组中的对象,只是指向它们的指针。 sys.getsizeof(1) 是 24。(Python 似乎没有在标记方面做任何聪明的事情,所以据我所知,fixnums 可以立即生效。)
    【解决方案2】:

    range(1000000000) 创建一个包含 10^9 个ints 的列表。这大约是 8GB(在 64 位系统上,每个 int 有 8 个字节)。然后,您尝试处理它以创建另一个 10^9 ints 列表。一个非常聪明的实现也许可以在 16GB 的机器上做到这一点,但这基本上是一个失败的原因。

    在 Python 2 中,您可以尝试使用 xrange,这可能有帮助,也可能没有帮助。我不确定 Python 3 的等价物是什么。

    【讨论】:

    • python 3 已弃用 xrange 生成器的范围实现,python 3 中的 range() 等同于 python 2 中使用 xrange()。
    • @Fanchi 谢谢。我可能会删除这个答案,因为我认为你的更好。
    猜你喜欢
    • 2020-09-30
    • 2011-02-08
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 2016-10-29
    • 1970-01-01
    相关资源
    最近更新 更多