通过multiprocessing.Queue传递numpy数组

时间:2014-01-28 15:25:01

标签: python numpy parallel-processing multiprocessing pickle

我正在使用multiprocessing.Queue在python进程之间传递float64的numpy数组。这工作正常,但我担心它可能没那么高效。

根据multiprocessing的文档,Queue上的对象将被腌制。在numpy数组上调用pickle会导致数据的文本表示,因此空字节将被字符串"\\x00"替换。

>>> pickle.dumps(numpy.zeros(10)) "cnumpy.core.multiarray\n_reconstruct\np0\n(cnumpy\nndarray\np1\n(I0\ntp2\nS'b'\np3\ntp4\nRp5\n(I1\n(I10\ntp6\ncnumpy\ndtype\np7\n(S'f8'\np8\nI0\nI1\ntp9\nRp10\n(I3\nS'<'\np11\nNNNI-1\nI-1\nI0\ntp12\nbI00\nS'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np13\ntp14\nb."

我担心这意味着我的阵列被昂贵地转换为原始大小的4倍,然后在另一个过程中转换回来。

有没有办法以原始未更改的形式通过队列传递数据?

我知道共享内存,但如果这是正确的解决方案,我不确定如何在其上构建队列。

谢谢!

2 个答案:

答案 0 :(得分:3)

问题不在于numpy,而是pickle如何表示数据的默认设置(作为字符串,因此输出是人类可读的)。您可以change the default settings for pickle来生成二进制数据。

import numpy
import cPickle as pickle

N = 1000
a0 = pickle.dumps(numpy.zeros(N))
a1 = pickle.dumps(numpy.zeros(N), protocol=-1)

print "a0", len(a0)   # 32155
print "a1", len(a1)   #  8133

另外,请注意,如果您想减少处理器的工作和时间,您应该使用cPickle而不是pickle(但由于使用二进制协议而节省的空间,无论pickle版本如何)。

在共享内存上:
关于共享内存的问题,有几点需要考虑。共享数据通常会给代码增加大量复杂性。基本上,对于使用该数据的每行代码,您需要担心另一个进程中的其他代码行是否同时使用该数据。这将有多难取决于你正在做什么。优点是可以节省来回发送数据的时间。 Eelco引用的问题是60GB阵列,为此,别无选择,必须共享。另一方面,对于大多数相当复杂的代码,决定共享数据只是为了节省几微秒或字节可能是最糟糕的过早优化之一。

答案 1 :(得分:3)

Share Large, Read-Only Numpy Array Between Multiprocessing Processes

这应该涵盖所有。无论使用何种协议,剔除不可压缩的二进制数据都是一种痛苦,所以这个解决方案更受欢迎。