Как использовать многопроцессорность в Python на объекте класса
Я довольно новичок в Python, и мой опыт связан с его использованием в моделировании Powerflow через API, предоставляемый в Siemens PSS/e. У меня есть сценарий, который я использую в течение нескольких лет, который запускает некоторое моделирование на большом наборе данных.
Чтобы быстро закончить, я обычно делю входные данные на несколько частей, а затем запускаю несколько экземпляров сценария в IDLE. Недавно я добавил графический интерфейс для входных данных и усовершенствовал код, чтобы он был более объектно-ориентированным, создав класс, в который графический интерфейс передает входные данные, но затем работает как оригинальный скрипт.
Мой вопрос: как мне разделить процесс внутри самой программы, а не делать несколько копий? Я немного прочитал о модуле mutliprocess, но я не уверен, как применить его к моей ситуации. По сути, я хочу иметь возможность создать N номер одного и того же объекта, каждый из которых работает параллельно.
Класс, который у меня сейчас (называется Bot), получает набор аргументов и создает вывод csv, пока он работает, пока не завершится. У меня есть отдельный блок кода, который собирает кусочки в конце, но сейчас мне просто нужно понять лучший подход к запуску нескольких объектов Bot после того, как я нажал run в моем GUI. Есть входы в GUI, чтобы указать количество N сегментов, которые будут использоваться.
Я заранее прошу прощения, если мой вопрос довольно расплывчатый. Спасибо за любую информацию, так как я как бы застрял и не знаю, где искать лучшие ответы.
2 ответа
Создайте список конфигураций:
configurations = [...]
Создайте функцию, которая принимает соответствующую конфигурацию и использует ваши Bot
:
def function(configuration):
bot = Bot(configuration)
bot.create_csv()
Создать Pool
из работников с любым количеством процессоров, которые вы хотите использовать:
from multiprocessing import Pool
pool = Pool(3)
Вызовите функцию несколько раз, что каждая конфигурация в вашем списке конфигураций.
pool.map(function, configurations)
Например:
from multiprocessing import Pool
import os
class Bot:
def __init__(self, inputs):
self.inputs = inputs
def create_csv(self):
pid = os.getpid()
print('TODO: create csv in process {} using {}'
.format(pid, self.inputs))
def use_bot(inputs):
bot = Bot(inputs)
bot.create_csv()
def main():
configurations = [
['input1_1.txt', 'input1_2.txt'],
['input2_1.txt', 'input2_2.txt'],
['input3_1.txt', 'input3_2.txt']]
pool = Pool(2)
pool.map(use_bot, configurations)
if __name__ == '__main__':
main()
Выход:
TODO: create csv in process 10964 using ['input2_1.txt', 'input2_2.txt']
TODO: create csv in process 8616 using ['input1_1.txt', 'input1_2.txt']
TODO: create csv in process 8616 using ['input3_1.txt', 'input3_2.txt']
Если вы хотите сделать жизнь немного менее сложной, вы можете использовать multiprocess
вместо multiprocessing
, так как есть лучшая поддержка для классов, а также для работы в переводчике. Как вы можете видеть ниже, теперь мы можем напрямую работать с методом в экземпляре класса, что невозможно с multiprocessing
,
>>> from multiprocess import Pool
>>> import os
>>>
>>> class Bot(object):
... def __init__(self, x):
... self.x = x
... def doit(self, y):
... pid = os.getpid()
... return (pid, self.x + y)
...
>>> p = Pool()
>>> b = Bot(5)
>>> results = p.imap(b.doit, range(4))
>>> print dict(results)
{46552: 7, 46553: 8, 46550: 5, 46551: 6}
>>> p.close()
>>> p.join()
Выше, я использую imap
, чтобы получить итератор результатов, который я просто добавлю в dict
, Обратите внимание, что вы должны закрыть свои бассейны после того, как вы сделали, чтобы очистить. В Windows вы также можете посмотреть на freeze_support
, для случаев, когда в противном случае код не запускается.
>>> import multiprocess as mp
>>> mp.freeze_support