【发布时间】:2018-06-02 07:33:02
【问题描述】:
我一直在尝试更多地了解 Python 的 multiprocessing 模块,并评估不同的进程间通信技术。我编写了一个基准,比较了Pipe、Queue 和Array(均来自multiprocessing)在进程之间传输numpy 数组的性能。完整的基准测试可以在here 找到。这是Queue 的测试的sn-p:
def process_with_queue(input_queue, output_queue):
source = input_queue.get()
dest = source**2
output_queue.put(dest)
def test_with_queue(size):
source = np.random.random(size)
input_queue = Queue()
output_queue = Queue()
p = Process(target=process_with_queue, args=(input_queue, output_queue))
start = timer()
p.start()
input_queue.put(source)
result = output_queue.get()
end = timer()
np.testing.assert_allclose(source**2, result)
return end - start
我在我的 Linux 笔记本电脑上运行了这个测试,对于 1000000 的数组大小,得到了以下结果:
Using mp.Array: time for 20 iters: total=2.4869s, avg=0.12435s
Using mp.Queue: time for 20 iters: total=0.6583s, avg=0.032915s
Using mp.Pipe: time for 20 iters: total=0.63691s, avg=0.031845s
看到Array 表现如此糟糕,我有点惊讶,因为它使用共享内存并且可能不需要酸洗,但我认为numpy 中肯定有一些我无法控制的复制。
但是,我在 Macbook 上运行了相同的测试(再次针对数组大小 1000000),得到以下结果:
Using mp.Array: time for 20 iters: total=1.6917s, avg=0.084587s
Using mp.Queue: time for 20 iters: total=2.3478s, avg=0.11739s
Using mp.Pipe: time for 20 iters: total=8.7709s, avg=0.43855s
真正的时间差异并不令人惊讶,因为当然不同的系统会表现出不同的性能。 令人惊讶的是相对时间的差异。
这是什么原因?这对我来说是一个非常令人惊讶的结果。看到 Linux 和 Windows,或 OSX 和 Windows 之间存在如此明显的差异,我不会感到惊讶,但我有点假设这些事情在 OSX 和 Linux 之间的行为非常相似。
This question 解决了 Windows 和 OSX 之间的性能差异,这似乎更令人期待。
【问题讨论】:
-
Value和Array类型依赖于Lock来确保数据安全。获取锁是一项相当昂贵的操作,因为它需要切换到内核模式。另一方面,序列化简单的数据结构是现代 CPU 大部分时间都在做的事情,因此它的成本相当低。从Array中删除Lock应该会显示更好的性能,但您不能排除数据的竞争条件。 -
@noxdafox 如果您查看完整的基准代码,您会发现我实际上没有对基准的
Array部分使用锁定。即便如此,这也只能说明Array在 Linux 上相对较差的性能,但并不一定说明 Linux 和 OSX 之间的差异。 -
你的 macbook 有固态硬盘,你的 linux 笔记本电脑有旋转磁盘吗?
-
它可以解释 Linux 中的 Array 缓慢。 Python 共享内存实现似乎是在文件系统上创建文件(请参阅stackoverflow.com/questions/44747145/…)。我认为 SSD 与旋转磁盘可以解释那里的差异。不过,它并没有解释为什么管道在 mac 上这么慢。
-
您应该考虑测量 CPU 时间而不是挂钟时间。
标签: python linux macos multiprocessing communication