【问题标题】:Parallelize distance calculation method with multiprocessing多处理并行化距离计算方法
【发布时间】:2015-07-11 10:49:39
【问题描述】:

这个问题和我前几天发的other one有关;我已经阅读了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)

有什么线索吗?

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

【问题讨论】:

标签: python python-2.7 distance python-multiprocessing


【解决方案1】:

我认为这里有很多混乱,所以我不确定我是否理解问题。

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

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

其他:

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

cpu_count() 调用是多余的,因为池已经生成了与默认 CPU 一样多的工作程序。

【讨论】:

  • 感谢您的回答。我解决了范围问题,但我得到了另一个与scipy.spatial.distance.cdist 相关的异常。如果你愿意,如果你知道发生了什么,你可以编辑你的答案。
  • 我希望您在已解决的情况下关闭此问题并打开一个新问题,在其中解释您遇到的新问题。由于其他人可能会阅读此问题,因此他们更容易拥有单独的上下文。
【解决方案2】:

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

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

【讨论】:

  • 我对多处理有点陌生,但似乎将 (1000, 2) 数组拆分为一千 (2,) 数组的方式并不能很好地利用 numpy 的功能。也许有一种方法可以将 (1000000, 2) 数组拆分为一千个 (1000, 2) 数组并将每个数组发送给工作人员。
  • 我想最明显的方法是将points 重塑为 (10, 100, 2) 然后vstack 将结果放在一起......
  • 这是一个很好的观点。我很担心应该使用multiprocessing.Queuemultiprocessing.Process 手动完成。我认为我有点等待可能的其他答案。感谢您的帮助。
  • 可能在将数组提供给pool.map 之前预先拆分数组,然后将块插入列表中可能是一种解决方案。假设使用numpy.split
  • 我认为你离原来的问题有点远;)
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-23
    • 1970-01-01
    • 2018-01-30
    • 2010-12-21
    • 1970-01-01
    • 2013-04-08
    相关资源
    最近更新 更多