【问题标题】:Python - How to share large dataset among multiple processes?Python - 如何在多个进程之间共享大型数据集?
【发布时间】:2020-02-18 20:41:12
【问题描述】:

我需要将一个大型数据集(大约 25GB 的图像)读入内存并从多个进程中读取。没有一个进程必须写入,只需读取。所有进程都使用 Python 的多处理模块启动,因此它们具有相同的父进程。他们在数据上训练不同的模型并相互独立运行。我之所以只想读一次而不是在每个进程中读取它的原因是机器上的内存是有限的。

我曾尝试使用 Redis,但不幸的是,当许多进程从中读取时它非常慢。还有其他选择吗?

是否有可能以某种方式让另一个进程仅用作“获取 ID x 的图像”功能?什么 Python 模块适合这个?否则,我正在考虑使用 werkzeug 或 Flask 实现一个小型网络服务器,但我不确定这是否会成为我的新瓶颈......

我想到的另一种可能性是使用线程而不是进程,但由于 Python 并没有真正做“真正的”多线程,这可能会成为我的新瓶颈。

【问题讨论】:

    标签: python multiprocessing


    【解决方案1】:

    如果你在linux上,并且内容是只读,你可以使用linux的fork继承机制。

    来自mp documentation

    比pickle/unpickle更好继承

    当使用 spawn 或 forkserver 启动方法时,许多类型来自 多处理需要是可腌制的,以便子进程可以使用 他们。但是,通常应该避免将共享对象发送到 使用管道或队列的其他进程。相反,您应该安排 程序,以便需要访问共享资源的进程 在其他地方创建的可以从祖先进程继承它。

    意思是:

    在 fork 子进程之前,请在 模块级别 变量(所有函数的全局变量)中准备大数据。

    然后在同一个模块中,以“fork”模式运行您的孩子的多处理set_start_method('fork')

    使用这个子进程将看到这个变量而不复制它。这是由于 linux fork 机制创建的子进程与父进程具有相同的内存映射(请参阅“写入时复制”)。

    【讨论】:

    • 太棒了!谢谢你。这比预期的要容易:-)而且现在真的很快。原来默认的启动方法(至少在我的机器上)已经是“fork”。我正在运行 linux。
    【解决方案2】:

    我建议mmapping the files,这样它们就可以在多个进程之间共享,也可以在适当的时候换入/换出

    具体细节取决于您所说的“25GB 图像”是什么意思以及这些模型希望如何访问图像

    基本思想是将图像预处理为适当的格式(例如,一个大的 4D uint8 numpy 数组或较小的数组,索引可以是 (image, row, column, channel))并将它们保存为可以有效使用的格式由模型。有关这方面的一些示例,请参见 numpy.memmap

    我建议将文件预处理为“离线”有用的格式,即不是模型训练的一部分,而是首先运行的单独程序。因为这可能需要一段时间,而且您可能不想每次都这样做

    【讨论】:

    • 我会看看这个。我的 25GB 图像是 cv2 读取的 png 图像,所以基本上只有 25GB 的 numpy 数组。我已经对它们进行了预处理并将其存储到 npy 文件中(每个图像一个)。
    • 好的,所以你建议有一个包含所有图像的数组。我可以这样做,但为了使它起作用,我必须填充图像,因为它们都有不同的分辨率。你还会推荐这个吗?我有一些 500x500 范围内的图像和一些 400x400 范围内的图像。无法将全部重新缩放为相同的大小,因为这会影响我的模型准确性。
    猜你喜欢
    • 1970-01-01
    • 2012-12-15
    • 2015-03-29
    • 2022-01-03
    • 1970-01-01
    • 2011-06-13
    • 2022-11-12
    • 2012-07-22
    • 2013-03-23
    相关资源
    最近更新 更多