2015-05-30 4 views
2

У меня есть класс, который ведет себя странно при доступе к нескольким потокам. Потоки запускаются во время обучения GridSearch sklearn (с заданиями = 3), поэтому я точно не знаю, как их вызывать.Python thread locking/class variable Инициализация путаницы

Мой класс сам по себе выглядит примерно так:

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

Threading сам по себе не ускоряет процессы python, узким местом которого является CPU, а не IO (чтение/запись) из-за глобальной блокировки интерпретатора (GIL). Чтобы получить ускорение, sklearn использует многопроцессорную обработку для распараллеливания. Это отличается от потоковой передачи тем, что объекты копируются в отдельный процесс и, следовательно, эффективно работают несколько копий вашего класса. Итак, каждый раз, когда запускается новый процесс, копируется ваш исходный, неинициализированный класс, который затем снова загружается.

Я думаю, что это основной модуль параллелизма, используемый sklearn для поиска в сетке. https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/externals/joblib/parallel.py

+0

Я полагаю, невозможно или неоправданно сложно разделить одну и ту же переменную класса среди всех процессов, не так ли? – Arne

+0

Хотя межпроцессное общение возможно в python, я не думаю, что sklearn предназначен для этого. Что удерживает вас от загрузки модулей перед запуском функции? – Gecko

+0

Тот факт, что они могут не понадобиться в зависимости от того, с какими параметрами вызывается скрипт. Но я думаю, что я просто загружу их один раз в начале, слишком сложно раскрыть их загрузку несколько раз. Спасибо за помощь, это позволяет избежать много времени, потраченного с моей стороны. – Arne

Смежные вопросы