2015-05-30 73 views
2

我有一個類,如果多線程訪問行爲奇怪。這些線程在sklearn的GridSearch培訓期間開始(工作= 3),所以我不知道它們是如何被調用的。Python線程鎖定/類變量初始化混淆

我的類本身看起來大致是這樣的:

from sklearn.base import BaseEstimator, TransformerMixin 
import threading 

class FeatureExtractorBase(BaseEstimator, TransformerMixin): 
    expensive_dependency = {} 
    lock = threading.lock() 
    is_loaded = False 

    @staticmethod 
    def load_dependencies(): 
     FeatureExtractorBase.lock.acquire() 
     if not FeatureExtractorBase.is_loaded: 
      print('first request, start loading..') 
      # load dependencies, takes a while 
      FeatureExtractorBase.is_loaded = True 
      print('done') 
     else: 
      pass 
     FeatureExtractorBase.lock.release() 

class ActualExtractor(FeatureExtractorBase): 
    def transform(self, data): 
     FeatureExtractorBase.load_dependencies() 
     # generate features from data using dependencies 
     return features 

此類使用什麼,我希望這將是延遲初始化。馬上初始化會導致問題,我不能再這樣做了。而且由於在一次程序調用期間該類會重新初始化幾次,因此每次在構造函數中初始化數據都會浪費時間。現在的問題是, 這不工作,我希望它的方式,這是輸出:

Starting training 
Fitting 3 folds for each of 1 candidates, totalling 3 fits 
first request, start loading.. 
first request, start loading.. 
first request, start loading.. 
done. 
done. 
done. 
Done 1 jobs  | elapsed: 56.2s 
Done 3 out of 3 | elapsed: 1.0min finished 

Starting evaluation 
first request, start loading.. 
done. 

只進不出三個線程什麼,我以爲會在同一時間被鎖定的區域,一分鐘之後在測試期間,再次輸入相同的區域 - 儘管is_loaded應該在此時設置爲True

這是我第一次在Python中處理線程,而且對於類仍然很笨拙,所以我確信我在這裏做錯了什麼。但我看不到什麼或在哪裏。

回答

1

線程本身不會加速Python進程的瓶頸是CPU,而不是由於全局解釋器鎖定(GIL)導致的IO(讀/寫)。 要實際獲得加速sklearn使用多處理進行並行化。這與線程的不同之處在於對象被複制到一個單獨的進程中,因此實際上有多個類的副本。 因此,每次啓動一個新進程時,都會複製原始的非初始化類,然後再次進行加載。

我認爲這是sklearn用於網格搜索的主要並行化模塊。 https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/externals/joblib/parallel.py

+0

我想在所有進程中共享相同的類變量是不可能的或不合理的困難,對吧? – Arne

+0

雖然進程間的通信是可能的python,我不認爲sklearn被設計來做到這一點。在運行該功能之前,什麼使您無法加載模塊? – Gecko

+0

事實上,它們可能不需要,具體取決於調用腳本的參數。但我想我會在開始時加載它們一次,看到它們被多次加載太令人沮喪了。感謝您的幫助,這可以避免浪費我很多時間。 – Arne