многопроцессорный разделяемый массив Python3 (только для чтения) - PullRequest
0 голосов
/ 07 февраля 2019

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

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

Я написал некоторый псевдокод, чтобы продемонстрировать мою идею:

import multiprocessing


def worker_func(data, args):
    # do sth...
    return res

def compute(data, process_num, niter):
    data
    result = []
    args = init()

    for iter in range(niter):
        args_chunk = split_args(args, process_num)
        pool = multiprocessing.Pool()
        for i in range(process_num):
            result.append(pool.apply_async(worker_func,(data, args_chunk[i])))
        pool.close()
        pool.join()
        # aggregate result and update args
        for res in result:
            args = update_args(res.get())

if __name__ == "__main__":
    compute(data, 4, 100)

Проблема в каждой итерации, я должен передавать данные в подпроцесс, который занимает очень много времени.

Я предложил два возможных решения:

  1. обмениваться данными между процессами (это ndarray), вот название этого вопроса.
  2. Поддерживать подпроцесс живым, как процесс демона или что-то ... и ждать вызова.При этом мне нужно только передать данные в самом начале.

Итак, есть ли какой-нибудь способ разделить массив только для чтения между процессами?Или, если у вас есть хорошая реализация решения 2, оно также работает.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

Если вам абсолютно необходимо использовать многопроцессорную обработку Python, то вы можете использовать многопроцессорную обработку Python вместе с Хранилище объектов плазмы Arrow для хранения объекта в общей памяти и доступа к нему от каждого из работников.См. этот пример , который делает то же самое, используя фрейм данных Pandas вместо массивного массива.

Если вам абсолютно не нужно использовать многопроцессорность Python, вы можете сделать это намного прощес Луч .Одним из преимуществ Ray является то, что он будет работать из коробки не только с массивами, но и с объектами Python, которые содержат массивы.

Под капотом Ray сериализует объекты Python, используя Apache Arrow ,который представляет собой макет данных с нулевым копированием и сохраняет результат в хранилище объектов плазмы Arrow .Это позволяет рабочим задачам иметь доступ только для чтения к объектам без создания своих собственных копий.Вы можете прочитать больше о , как это работает .

Вот измененная версия вашего примера, которая работает.

import numpy as np
import ray

ray.init()

@ray.remote
def worker_func(data, i):
    # Do work. This function will have read-only access to
    # the data array.
    return 0

data = np.zeros(10**7)
# Store the large array in shared memory once so that it can be accessed
# by the worker tasks without creating copies.
data_id = ray.put(data)

# Run worker_func 10 times in parallel. This will not create any copies
# of the array. The tasks will run in separate processes.
result_ids = []
for i in range(10):
    result_ids.append(worker_func.remote(data_id, i))

# Get the results.
results = ray.get(result_ids)

Обратите внимание, что если мы пропустили строку data_id = ray.put(data) и вместо того, чтобы вызывать worker_func.remote(data, i), массив data будет сохраняться в общей памяти один раз за вызов функции, что будет неэффективно.Сначала вызвав ray.put, мы можем сохранить объект в хранилище объектов один раз.

0 голосов
/ 07 февраля 2019

Концептуально для вашей проблемы использование mmap является стандартным способом.Таким образом, информация может быть извлечена из отображенной памяти несколькими процессами

Базовое понимание mmap:

https://en.wikipedia.org/wiki/Mmap

Python имеет модуль "mmap" (import mmap)

Документация по стандарту Python и некоторые примеры приведены ниже по ссылке

https://docs.python.org/2/library/mmap.html

...