Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 如何在多处理包中锁定特定的数组索引?_Python 3.x_Multiprocessing_Python Multiprocessing - Fatal编程技术网

Python 3.x 如何在多处理包中锁定特定的数组索引?

Python 3.x 如何在多处理包中锁定特定的数组索引?,python-3.x,multiprocessing,python-multiprocessing,Python 3.x,Multiprocessing,Python Multiprocessing,我有一个multiprocessing.manager.Array对象,该对象将由多个工作人员共享以记录观察到的事件:数组中的每个元素都保存不同事件类型的记录。增加计数需要读写操作,所以我认为为了避免竞争条件,每个工人都需要请求一个覆盖两个阶段的锁,例如 with lock: my_array[event_type_index] += 1 我的直觉是,应该可以在特定数组元素上设置锁。使用这种类型的锁,worker#1可以在worker#2递增元素2的同时递增元素1。这对我的应用程序(n

我有一个
multiprocessing.manager.Array
对象,该对象将由多个工作人员共享以记录观察到的事件:数组中的每个元素都保存不同事件类型的记录。增加计数需要读写操作,所以我认为为了避免竞争条件,每个工人都需要请求一个覆盖两个阶段的锁,例如

with lock:
    my_array[event_type_index] += 1
我的直觉是,应该可以在特定数组元素上设置锁。使用这种类型的锁,worker#1可以在worker#2递增元素2的同时递增元素1。这对我的应用程序(n-gram计数)特别有用,因为数组长度非常大,冲突很少

但是,我不知道如何为数组请求元素锁。在
多处理
中是否存在这种情况,或者是否存在解决方法

为了了解更多内容,我在下面介绍了我当前的实现:

import multiprocessing as mp
from queue import Empty

def count_ngrams_in_sentence(n, ngram_counts, char_to_idx_dict, sentence_queue, lock):
    while True:
        try:
            my_sentence_str = sentence_queue.get_nowait()
            my_sentence_indices = [char_to_idx_dict[i] for i in my_sentence_str]
            my_n = n.value
            for i in range(len(my_sentence_indices) - my_n + 1):
                my_index = int(sum([my_sentence_indices[i+j]*(27**(my_n - j - 1)) \
                                    for j in range(my_n)]))
                with lock:  # lock the whole array?
                    ngram_counts[my_index] += 1
            sentence_queue.task_done()
        except Empty:
            break
    return

if __name__ == '__main__':
    n = 4
    num_ngrams = 27**n
    num_workers = 2
    sentences = [ ... list of sentences in lowercase ASCII + spaces ... ]

    manager = mp.Manager()
    sentence_queue = manager.JoinableQueue()
    for sentence in sentences:
        sentence_queue.put(sentence)
    n = manager.Value('i', value=n, lock=False)
    char_to_idx_dict = manager.dict([(i,ord(i)-97) for i in string.ascii_lowercase] + [(' ', 26)],
                                    lock=False)
    lock = manager.Lock()
    ngram_counts = manager.Array('l', [0]*num_ngrams, lock=lock)
''
    workers = [mp.Process(target=count_ngrams_in_sentence,
                          args=[n,
                                ngram_counts,
                                char_to_idx_dict,
                                sentence_queue,
                                lock]) for i in range(num_workers)]
    for worker in workers:
        worker.start()
    sentence_queue.join()

Multiprocessing.manager.Array带有内置锁。必须切换到RawArray

有一个锁的列表。在修改标记之前,请获取阵列的锁。然后释放

locks[i].acquire()
array[i,:]=0
locks[i].release()
如前所述,如果数组是MultiProcessing.RawArray或类似的数组,则多个进程可以同时读取或写入。对于某些类型的数组,对数组的读/写本质上是原子的——锁本质上是内置的。在继续之前,请仔细研究这一点


至于性能,在Python中,索引到列表的时间大约为纳秒,获取和释放锁的时间大约为微秒。这不是什么大问题。

哦,该死,我有一个类似的问题@梅瓦尔:你有什么进展吗?很抱歉,我从来没有解决过这个问题,@mozboz——不过祝你好运!谢谢你的回复。我没有太多的数组元素,所以只使用了与我的数据数组ID相同的锁的单独数组。不知道这是否有效,但还没有到那个阶段。