Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 多处理IOError:消息长度错误_Python_Numpy_Multiprocessing_Pool_Ioerror - Fatal编程技术网

Python 多处理IOError:消息长度错误

Python 多处理IOError:消息长度错误,python,numpy,multiprocessing,pool,ioerror,Python,Numpy,Multiprocessing,Pool,Ioerror,将大参数传递给map函数时,我得到一个IOError:bad message length。我怎样才能避免这种情况? 当我设置N=1500或更大时,会发生错误 代码是: import numpy as np import multiprocessing def func(args): i=args[0] images=args[1] print i return 0 N=1500 #N=1000 works fine images=[] for

将大参数传递给
map
函数时,我得到一个
IOError:bad message length
。我怎样才能避免这种情况? 当我设置
N=1500
或更大时,会发生错误

代码是:

import numpy as np
import multiprocessing

def func(args):
    i=args[0]
    images=args[1]
    print i
    return 0

N=1500       #N=1000 works fine

images=[]
for i in np.arange(N):
    images.append(np.random.random_integers(1,100,size=(500,500)))

iter_args=[]
for i in range(0,1):
    iter_args.append([i,images])

pool=multiprocessing.Pool()
print pool
pool.map(func,iter_args)
多处理
的文档中,有一个函数
recv_bytes
会引发IOError。可能是因为这个吗?()

编辑 如果我使用
images
作为numpy数组而不是列表,我会得到一个不同的错误:
SystemError:NULL result,PyObject\u调用中没有错误
。 稍有不同的代码:

import numpy as np
import multiprocessing

def func(args):
    i=args[0]
    images=args[1]
    print i
    return 0

N=1500       #N=1000 works fine

images=[]
for i in np.arange(N):
    images.append(np.random.random_integers(1,100,size=(500,500)))
images=np.array(images)                                            #new

iter_args=[]
for i in range(0,1):
    iter_args.append([i,images])

pool=multiprocessing.Pool()
print pool
pool.map(func,iter_args)
EDIT2我使用的实际功能是:

def func(args):
    i=args[0]
    images=args[1]
    image=np.mean(images,axis=0)
    np.savetxt("image%d.txt"%(i),image)
    return 0
此外,
iter_参数
不包含相同的图像集:

iter_args=[]
for i in range(0,1):
    rand_ind=np.random.random_integers(0,N-1,N)
    iter_args.append([i,images[rand_ind]])

Python可能会将数据加载到RAM内存中,您需要该内存才能使用。你检查过你的电脑内存使用情况吗

同样正如Patrick提到的,如果要加载3GB的数据,请确保在达到32位内存限制时使用64位版本的Python。这可能会导致进程崩溃:


另一个改进是使用Python3.4而不是2.7。Python 3实现似乎针对非常大的范围进行了优化,请参见

您正在创建一个池并将所有图像同时发送到func()。如果您可以一次处理一个图像,请尝试以下方法,使用Python 2.7.10在35秒内以N=10000的速度运行到完成:

import numpy as np
import multiprocessing

def func(args):
    i = args[0]
    img = args[1]
    print "{}: {} {}".format(i, img.shape, img.sum())
    return 0

N=10000

images = ((i, np.random.random_integers(1,100,size=(500,500))) for i in xrange(N))
pool=multiprocessing.Pool(4)
pool.imap(func, images)
pool.close()
pool.join()
这里的关键是使用迭代器,这样就不必同时在内存中保存所有数据。例如,我将包含所有数据的数组中的图像转换为生成器表达式,以便仅在需要时创建图像。您可以修改它以从磁盘或其他任何地方加载图像。我还使用了pool.imap而不是pool.map

如果可以,请尝试在worker函数中加载图像数据。现在,您必须序列化所有数据并将其发送到另一个进程。如果图像数据较大,这可能是一个瓶颈

[现在更新,我们知道func必须一次处理所有图像]

你可以在你的图像上做一个迭代平均。这里有一个不使用多处理的解决方案。要使用多处理,您可以将图像分成块,并将这些块分发到池中

import numpy as np

N=10000
shape = (500,500)

def func(images):
    average = np.full(shape, 0)
    for i, img in images:
        average += img / N
    return average

images = ((i, np.full(shape,i)) for i in range(N))

print func(images)

运行程序时,它实际上会给我一个明显的错误:

OSError: [Errno 12] Cannot allocate memory
正如其他用户所提到的,解决问题的方法很简单:添加内存(很多)或更改程序处理图像的方式


它使用如此多内存的原因是,您在模块级别为图像分配内存。因此,当多进程分叉您的进程时,它也会复制所有的图像(根据,这不是免费的),这是不必要的,因为您还将图像作为多进程模块也使用ipc和pickle复制的函数的参数,这仍然可能导致内存不足。尝试其他用户提出的一种解决方案。

这就是解决问题的方法:将图像声明为全局

import numpy as np
import multiprocessing


N=1500       #N=1000 works fine

images=[]
for i in np.arange(N):
    images.append(np.random.random_integers(1,100,size=(500,500)))

def func(args):
    i=args[0]
    images=images
    print i
    return 0

iter_args=[]
for i in range(0,1):
    iter_args.append([i])

pool=multiprocessing.Pool()
print pool
pool.map(func,iter_args)

您正在传递3GB的图像。如果它们是从文件系统开始的,也许您可以简单地将文件名排队。如果您正在生成它们,您可以使用多处理数组类在共享内存中创建数据,这样队列中实际的数据量(例如,关于共享内存的信息)就更小了。对于我来说,在ubuntu上也有同样的错误
IOError:bad message length
func()是否需要同时对所有1500个图像进行操作,或者它可以一次在一个图像上工作?你想实现什么?您给出的代码似乎在毫无理由地使用多处理:它将启动一个子进程,并将所有图像传递给该进程。你真的不想要很多子进程,每个子进程一次处理一个图像吗?我在我的答案中添加了一个解决方案(没有多重处理)。它可以在相当现代化的硬件上快速处理1500个映像,而无需进行多处理。这里的一个关键点是,您需要关闭并加入池(使用
pool.close()
pool.join()
)。这会将所有映像复制到每个进程,这使得此方法在缩放方面非常糟糕