Python multiprocessing.Pool 无法 pickle mxnet.mod.Module 对象

Python multiprocessing.Pool cannot pickle mxnet.mod.Module object

我大概是这样的:

import mxnet as mx
import cv2
from multiprocessing import Pool
from itertools import repeat

num_worker=4
CNNNet=[]
img = cv2.imread('../datasets/1.jpg')
sym, arg_params, aux_params = mx.model.load_checkpoint('det1', 0)
for i in range(num_worker):
    worker_net = mx.mod.Module(symbol=sym,label_names=None)
    worker_net.bind(data_shapes=[('data', (1, 3, 1000, 1000))],for_training=False)
    worker_net.set_params(arg_params,aux_params)
    CNNNet.append(worker_net)
pool = Pool(num_worker)
threshold = 0.6
res = pool.map(do_work_warpper,zip(repeat(img),CNNNet[:num_worker],repeat(threshold)))

do_work_warpper() 函数是:

def do_work_warpper(args):
    return do_work(*args)
def do_work(img,net,threshold):
    #do image predict job here
    return res

我对 multiprocessing.Poolmx.mod.Module 对象一起使用时的问题感到困惑,我在 python3.6:

中得到错误
TypeError: can't pickle module objects

或 python2.7:

PicklingError: Can't pickle <type 'module'>: attribute lookup __builtin__.module failed

任何建议将不胜感激。

你得到这个异常的原因是因为 multiprocessing 需要能够 pickle 你传递给你的工作人员的变量,以便在它产生的各种进程之间传递它们。

错误:

TypeError: can't pickle module objects

表明您传递给 Pool 的变量之一包含一个模块(或一个 class 具有模块作为属性)。

为了演示这个问题,请看一下这两个 class:

import os

class Pickable: 
    a = 1

class UnPickable:
    def __init__(self):
        self.mod = os

如果您尝试 pickle 这两个 class 的实例,您将得到:

In [11]: pickle.dumps(Pickable())
Out[11]: b'\x80\x03c__main__\nPickable\nq\x00)\x81q\x01.'

In [10]: pickle.dumps(UnPickable())
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-10-7d4d725a1c6d> in <module>()
----> 1 pickle.dumps(UnPickable())

TypeError: can't pickle module objects

话虽这么说 - 要么你创建自己的 class 来模仿 mx.mod.Module 的功能,但它是可序列化的 - 或者(我认为更好的解决方案)使用简单的 python-内置类型将变量传递给 Pool 的 worker 并在其中自行构建 mx.mod.Module 个实例。