【发布时间】:2013-11-09 06:05:24
【问题描述】:
我正在依次对 3 个不同的 numpy 2D 数组执行一些大型计算。阵列很大,每个 25000x25000。每次计算都需要大量时间,因此我决定在服务器上的 3 个 CPU 内核上并行运行其中的 3 个。我遵循标准的多处理指南并创建 2 个进程和一个工作函数。两个计算通过 2 个进程运行,第三个计算在本地运行,没有单独的进程。我将巨大的数组作为进程的参数传递,例如:
p1 = Process(target = Worker, args = (queue1, array1, ...)) # Some other params also going
p2 = Process(target = Worker, args = (queue2, array2, ...)) # Some other params also going
Worker 函数将两个 numpy 向量(一维数组)发送回一个附加在队列中的列表中,例如:
queue.put([v1, v2])
我没有使用multiprocessing.pool
但令人惊讶的是我没有得到加速,它实际上运行速度慢了 3 倍。传递大型数组需要时间吗?我无法弄清楚发生了什么。我应该使用共享内存对象而不是传递数组吗?
如果有人能提供帮助,我将不胜感激。
谢谢。
【问题讨论】:
-
作为一种基准测试,尝试计算腌制/解封阵列所需的时间。正因为您正在连续调度工作人员,您必须等待整个 pickle>unpickle 循环在第一个数组上完成,然后才能开始。您也可能会淹没您的 i/o 流或输出队列。考虑尝试使用进程池来执行此操作,并对每个工作迭代可能的最小和最简单的数据集合进行操作,这样您的工作人员就可以在您完成填充输入缓冲区之前开始工作,而不必提取尽可能多的数据在开始之前结束。
-
子进程不共享内存,因此要将参数从父进程传递给子进程,它们必须经过序列化>反序列化过程。
mutliprocessing将参数传递给子进程的方式是在父进程中腌制参数,然后使用pickle模块在子进程中解开它们。处理小而简单的数据通常没什么大不了的,但是由于您使用的是巨大的 numpy 数组,因此您的数据既不小也不简单。基本上,如果您可以将必须传递给工作人员的数据减少为少量更原始的类型,这可能会有所帮助。 -
@Saullo Castro 谢谢。我不知道幕后这个泡菜+解酒。我是python编程的新手,现在我明白了。我现在试试 np.memmap。如果有任何问题,我会在这里发布。不过非常感谢。
-
一旦你开始在巨大的数组上做一些事情,你的内存布局就变得非常重要。在您调用的方法中执行 += 之类的操作可以加快速度,只是因为内存分配比实际执行您想要执行的操作需要更多时间。
-
@Saullo Castro 只是一个简单的问题,我查看了工人池。这很简单。我只想知道使用工人池是否比手动创建多个子流程更可取?我知道我有 3 个矩阵或 np.arrays 所以我需要 3 个子进程。那么,如果我不使用池并像我一样手动创建进程,会有什么问题吗?在这两种情况下都可能存在pickle-unpickle 和内部内存分配和映射问题。如果你能在这方面提供帮助。或者如果其他人可以提供帮助。
标签: python arrays numpy process multiprocessing