Мутиобработка Python с большими общими данными

Я использую python для разработки приложения для обработки данных с помощью модуля mutliprocessing, код выглядит так:

import multiprocessing

globalData = loadData() #very large data 

def f(v):
    global globalData
    return someOperation(globalData,v)

if __name__ == '__main__':
    pool = multiprocessing.Pool()
    arr = loadArray() #some big list
    res = pool.map(f,arr)

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

Python должен использовать механизм копирования при записи, когда вы используете глобальные переменные ... Вы изменяете свой объект globalData? Если это так, вы можете захотеть использовать многопроцессорность вместо многопроцессорной обработки.

Fred 18.12.2018 12:36

Нет, он предназначен только для чтения, но кажется, что он не будет копировать его, если я использую Windows, или я что-то пропускаю?

ammcom 18.12.2018 12:43

Ну ... я не знаю, что тебе сказать. Данные только для чтения, совместно используемые процессами, не должны копироваться. Релевантно: stackoverflow.com/questions/38084401/…

Fred 18.12.2018 12:46
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
3
262
2

Ответы 2

Я также новичок в python, но если я понимаю ваш вопрос, это очень просто: в следующем скрипте мы используем 5 рабочих, чтобы получить квадрат первых 10000 чисел.

import multiprocessing

globalData = range(10000) #very large data 

def f(x):
  return x*x

if __name__ == '__main__':
    pool = multiprocessing.Pool(5)
    print(pool.map(f,globalData))

Проблема в том, что globalData необходимо загружать из внешнего хранилища, что требует времени, поэтому, если он находится в памяти, я могу просто скопировать его в дочерние процессы.

ammcom 19.12.2018 20:34

Если вам нужно обработать огромное количество файлов, посмотрите на это: medium.com/@ageitgey/… Если вы хотите обработать один огромный файл, то посмотрите на этот stackoverflow.com/questions/11196367/…, этот stackoverflow.com/questions/42404292/… или этот stackoverflow.com/questions/28641059/…

Meziane 20.12.2018 08:53

Многопроцессорность в ms-windows работает иначе, чем в UNIX-подобных системах.

В UNIX-подобных системах есть системный вызов fork, который делает копию текущего процесса. В современных системах с управлением виртуальной памятью «копирование при записи» это даже не очень затратная операция.

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

Дело в том, что в ms-windows нет fork. Вместо него есть CreateProcess. Итак, в ms-windows это происходит:

The parent process starts a fresh python interpreter process. The child process will only inherit those resources necessary to run the process objects run() method. In particular, unnecessary file descriptors and handles from the parent process will not be inherited. Starting a process using this method is rather slow compared to using fork or forkserver.

Итак, поскольку ваша функция ссылается на глобальные данные, она будет загружена. Но каждый дочерний процесс будет загружать его отдельно.

Что вы можете попробовать, так это заставить ваши процессы загружать данные, используя mmap с ACCESS_READ. Я бы сказал ожидать, что подсистема памяти ms-windows достаточно умен, чтобы загружать данные только один раз, если один и тот же файл загружается несколькими процессами.

Другие вопросы по теме