多进程并行距离计算方法

Parallelize distance calculation method with multiprocessing

此问题与 I posted days ago; I've read this question 有关 multiprocessing 使用实例方法酸洗相关的问题。问题是我不明白如何将提供的解决方案应用到我的案例中:

def _pickle_method(method):
    # Author: Steven Bethard
    # http://bytes.com/topic/python/answers/552476-why-cant-you-pickle-instancemethods
    func_name = method.im_func.__name__
    obj = method.im_self
    cls = method.im_class
    cls_name = ''
    if func_name.startswith('__') and not func_name.endswith('__'):
        cls_name = cls.__name__.lstrip('_')
    if cls_name:
        func_name = '_' + cls_name + func_name
    return _unpickle_method, (func_name, obj, cls)

def _unpickle_method(func_name, obj, cls):
    # Author: Steven Bethard
    # http://bytes.com/topic/python/answers/552476-why-cant-you-pickle-instancemethods
    for cls in cls.mro():
        try:
            func = cls.__dict__[func_name]
        except KeyError:
            pass
        else:
            break
    return func.__get__(obj, cls)

copy_reg.pickle(types.MethodType, _pickle_method, _unpickle_method)

class Circle(Feature):
# Stuff...
    def __points_distance(self,points):
        xa = n.array([self.xc,self.yc]).reshape((1,2))
        d = n.abs(dist.cdist(points,xa) - self.radius)
        return d

def points_distance(self,points,pool=None):
    if pool:
        return pool.map(self.__points_distance,points)
    else:
        return self.__points_distance(points)

这在 运行 时给出 ValueError: XA must be a 2-dimensional array 错误:

import tra.features as fts
import numpy as np
import multiprocessing as mp

points = np.random.random(size=(1000,2))
circle_points = np.random.random(size=(3,2))

feature = fts.Circle(circle_points)

pool = mp.Pool()
ds = feature.points_distance(points,pool=pool)

但它(显然)在执行时有效:

pool = None
ds = feature.points_distance(points,pool=pool)

有什么线索吗?

这与 (I checked this 实现不同)因为该方法在另一个 class 中使用,它实例化 Circle class 并调用它的 points_distance 方法.在任何情况下,另一个区别是 points_distance 方法使用 scipy.spatial.distance.cdist 期望 (n,2)-shaped numpy.ndarray。它在使用串行版本时有效,但在并行使用时引发我提到的异常。我想有一个关于 cPickle 传递参数的警告。

我觉得这里有点混乱,所以我不确定我是否理解这个问题。

异常 NameError: global name 'pool' is not defined 不是由于酸洗问题,而是由于范围问题。

该方法在其范围内找不到 pool。尝试通过将 pool 引用传递给该方法来修复它。

其他:

pool = mp.Pool(mp.cpu_count())

cpu_count() 调用是多余的,因为默认情况下池已经产生了与您拥有的 CPU 一样多的工作线程。

您传递给 pool.mappoints 数组的形状为 (1000, 2)。当 pool.map 拆分它作为 points 参数传递给 __points_distance 时, 那个 数组只有形状 (2,)。

尝试在调用 cdist 之前将 points.shape = (1, 2) 添加到 __points_distance 的正文中。

pool 变量在 Circle class 之外定义,因此 points_distance() will be unable to findpool` 在其命名空间中:

向接受 pool 的 Circle 或 Feature 添加一个构造函数,并将您要使用的池传递给 RansacFeature,我假设它会为您实例化 Circle