2013-12-05 1 views
4

Я использую autovivification для хранения данных в многопроцессорной настройке. Однако я не могу понять, как включить его в функцию диспетчера многопроцессорности.autovivificating многопроцессорный менеджер() словари в python

Код моей автоподвижности исходит от Multiple levels of 'collection.defaultdict' in Python и отлично работает, когда не происходит многопроцессорной обработки.

class vividict(dict): 
    def __getitem__(self, item): 
     try: 
      return dict.__getitem__(self, item) 
     except KeyError: 
      value = self[item] = type(self)() 
      return value 

Мой multiproc код относительна Simpel:

if __name__ == "__main__": 
    man = Manager() 
    ngramDict = man.dict() 
    print(ngramDict) # {} 
    s_queue = Queue() 

    aProces = Process(target=insert_ngram, args=(s_queue,ngramDict,)) 
    aProces.start() 
    aProces.join() 
    print(ngramDict) # {} 
    write_to_file() 

В insert_ngram словаре читается, написано и обновлена:

def insert_ngram(sanitize_queue, ngramDict): 
    ngramDict = Vividict() # obviously this overwrites the manager 
    try: 
     for w in iter(s_queue.get, None): 
     if ngramDict[w[0]][w[1]][w[2]][w[3]][w[4]]: 
      ngramDict[w[0]][w[1]][w[2]][w[3]][w[4]]+=int(w[5]) 
     else: 
      ngramDict[w[0]][w[1]][w[2]][w[3]][w[4]]=int(w[5]) 
    print(ngramDict) # prints the expected ngramdict 
    return 
except KeyError as e: 
    print("Key %s not found in %s" % (e, ngramDict)) 
except Exception as e: 
    print("%s failed with: %s" % (current_process().name, e)) 

Я пробовал серию, что я думал, были хорошие решения, но я не могу заставить его работать, за исключением звонка write_to_file в insert_ngram, но это не очень аккуратное решение.

Есть ли возможность получить Manager.dict() для autovivifacte?

--------- UPDATE 6-12-2013 --------

С Manager() provdes прокси, любые мутации в виде manager.Dict() в пределах подпроцесса Арен» t сохранен/сохранен. (Смотри также: How does multiprocessing.Manager() work in python?) Это может быть решена folows:

def insert_ngram(sanitize_queue, ngramDict): 
    localDict = Vividict() 
    localDict.update(ngramDict) 
    #do stuff 
    ngramDict.update(ngramiDict) 

Я жду моей машины, чтобы закончить некоторые задачи, так что я могу видеть, как это работает. Кажется, что это был удар производительности, чтобы копировать Dicts вверх и вниз. (Мои Dicts запустить в 200MB +)

--------- UPDATE 8-12-2013 -------- В моем приложении, dict.update() только ударил один раз, так что даже если Dict составляет ~ 200Mb +, в целом это не большое влияние на производительность ...

ответ

2

Многопроцессорная обработка Manager() обеспечивает прокси-словарь для словаря или списка. Любые мутации в manager.Dict() в рамках подпроцесса не сохраняются и не отслеживаются. Таким образом, нужно копировать мутации в прокси-переменную, принадлежащую диспетчеру. (смотри также: How does multiprocessing.Manager() work in python?)

Это может быть решена folows:

def insert_ngram(queue, managerDict): 
    # create a local dictionary with vivification 
    localDict = Vividict() 
    # copy the existing manager.dict to the local dict. 
    localDict.update(managerDict) 
    #do stuff 
    # copy the local dictionary to the manager dict 
    managerDict.update(localDict) 
    return 

Хотя это кажется какой-то серьезный накладных расходов, в данном случае это не так уж плохо, так как менеджер словарей необходимо лишь обновить () перед присоединением к основному процессу.