2015-07-11 86 views
2

這個問題與我在幾天前發佈的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實現),因爲該方法是實例化Circle類,並調用其points_distance方法另一個類中使用。在任何情況下,另一個不同之處在於points_distance方法使用scipy.spatial.distance.cdist,它預期(n,2)形numpy.ndarray。它在使用串行版本時起作用,但引發了我在並行使用時提到的異常。我想有一個關於cPickle傳遞的參數的警告。

+1

[Can not pickle 使用python的多處理Pool.map()]時可能的重複(http://stackoverflow.com/questions/1816958/cant-pickle-type-in​​stancemethod-when- using-pythons-multiprocessing-pool-ma) – User

+1

@用戶感謝您的幫助。我已經檢查了你提供的答案,但目前不適合我。 – SolidSnake

回答

1

您傳遞給pool.mappoints數組的形狀爲(1000,2)。當pool.map分裂它作爲points自變量通過__points_distance,陣列只有形狀(2,)。

在致電cdist之前,嘗試將points.shape = (1, 2)添加到__points_distance的正文中。

+1

我對多處理有點新,但它似乎將你的(1000,2)數組拆分爲一千(2,)個數組並不能很好地利用numpy的功能。也許有一種方法可以將一個(1000000,2)數組拆分爲一千(1000,2)個數組,然後將每個數組發送給一個工作者。 – codewarrior

+0

我想明顯的方​​法是重塑'points'到(10,100,2),然後'vstack'結果在一起.... – codewarrior

+0

這是一個很好的觀點。我很擔心它應該使用'multiprocessing.Queue'和'multiprocessing.Process'手動完成。我想,我有點在等待可能的其他答案。謝謝你的幫助。 – SolidSnake

3

我認爲這裏有一些混亂,所以我不確定我是否理解這個問題。

例外NameError: global name 'pool' is not defined不是由於酸洗問題,而是由於範圍問題。該方法在其範圍內找不到pool。嘗試通過將pool引用傳遞給方法來修復它。

其他的事情:

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

cpu_count()電話是多餘的,因爲池已產卵儘可能多的工人,你的CPU在默認情況下。

+0

感謝您的回答。我解決了範圍問題,但我得到了另一個與'scipy.spatial.distance.cdist'相關的異常。如果你想要,你可以編輯你的答案,如果你知道發生了什麼事情。 – SolidSnake

+0

我寧願你解決這個問題,並解決你遇到的新問題,並打開一個新的問題。正如其他人可能會讀到這個問題,他們會更容易有一個單獨的上下文。 – noxdafox

0

pool變量在其命名空間Circle類的外部定義,所以points_distance() will be unable to find pool`:

添加一個構造函數來圓或功能,它接受一個pool,並通過您要使用RansacFeature池,這我假設爲你實例化Circle