Форум сайта python.su
Всем добрый день. Подскажите, пожалуйста, как можно:
1. Создать одну переменную (или массив) и использовать её для чтения в разных процессах? (переменная start_time в коде ниже)
2. Создать одну переменную, которую можно использовать и для чтения и для записи в разных процессах? (переменная counter в коде ниже)
Нужно использование именно multiprocessing, а не multithreading. Читал про Value и Array, но пока не смог понять как их их использовать..
from multiprocessing import Pool from datetime import datetime def main(link): global start_time global counter print(start_time) print(link) counter += 1 print(counter) if __name__ == '__main__': global start_time global counter counter = 0 start_time = datetime.now() links = [1,2,3] m = 3 pool = Pool(m) pool.map(main, links) pool.close() pool.join()
Отредактировано Room_on (Фев. 25, 2019 18:28:18)
Офлайн
Room_on
Принципиальное ограничение процессов - индивидуальное для процесса адресное пространство. (хотя на самом деле можно получить разделяемую память, но не в вашем случае). Межпроцессное взаимодействие осуществляется не так.
https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D0%B6%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%BD%D0%BE%D0%B5_%D0%B2%D0%B7%D0%B0%D0%B8%D0%BC%D0%BE%D0%B4%D0%B5%D0%B9%D1%81%D1%82%D0%B2%D0%B8%D0%B5
Офлайн
FishHook
Room_onПринципиальное ограничение процессов - индивидуальное для процесса адресное пространство. (хотя на самом деле можно получить разделяемую память, но не в вашем случае)
Офлайн
Room_onУважаемый друг, Value - это некоторое значение, ценность величина. Array - это массив. Что вы имеете в виду? Вы бы хоть ссылки давали, или примеры кода, или хотя бы намекнули, какую библиотеку смотреть и где конкретные классы Value и Array искать.
Мне казалось Value и Array как раз для этого.
Офлайн
from multiprocessing import Value, Array
https://docs.python.org/2/library/multiprocessing.html#sharing-state-between-processes
Отредактировано Room_on (Фев. 26, 2019 07:30:59)
Офлайн
Room_onну дык есть же пример, вы сами его приводите
Читал про Value и Array, но пока не смог понять как их их использовать..
Room_onтам вроде адкватный пример жи приведен, все работает, можете скопировать и проверить, что вам конкретно непонятно в использовании Value и Array?
https://docs.python.org/2/library/multiprocessing.html#sharing-state-between-processes
[code python][/code]
Отредактировано PEHDOM (Фев. 26, 2019 12:04:54)
Офлайн
PEHDOMЯ не понимаю, как использовать их вместе с pool.map
что вам конкретно непонятно в использовании Value и Array?
Отредактировано Room_on (Фев. 28, 2019 08:52:44)
Офлайн
Room_onтут как раз разницы никакой, вы можете Value и Array передать в два, три… миллион процессов с ровно тем же результатов.
В примере Value и Array передаются в один процесс, а мне нужно передать их в несколько процессов + список, значения из которого будут разбираться процессами и запускать одновременное выполнение функции.
Room_onа вот с pool.map там все намного веселее, если вы попытаетесь передать их так же как и “простом примере” то получите исключение типа такого:
Я не понимаю, как использовать их вместе с pool.map
from multiprocessing import Pool, Value from datetime import datetime counter = None start_time = None def init(cntr, start_t): #инициализатор для каждого процесса global counter global start_time counter = cntr start_time = start_t def main(link): with counter.get_lock(): counter.value += 1 print(counter.value, link, start_time) if __name__ == '__main__': counter = Value('i', 0) start_time = datetime.now() links = ['a','b','c','d', 'e', 'f'] m = 3 with Pool(processes=m, initializer = init, initargs = (counter, start_time)) as pool: pool.map(main, links) pool.close() pool.join()
from multiprocessing import Pool, Value from datetime import datetime def init(func, counter, start_time): #инициализатор для каждого процесса # передаем счетчик в тупую нашей функции, ведь функция это тоже обьект :) func.counter = counter func.statr_time = start_time def main(link): counter = main.counter # вобщем это необязательно, можно просто start_time = main.start_time # писать везде main.counter или main.start_time with counter.get_lock(): # всемсто counter и start_time counter.value += 1 # print(counter.value, link, start_time) if __name__ == '__main__': counter = Value('i', 0) start_time = datetime.now() links = ['a','b','c','d', 'e', 'f'] m = 3 with Pool(processes=m, initializer = init, initargs = (main, counter, start_time)) as pool: pool.map(main, links) pool.close() pool.join()
from multiprocessing import Pool, Manager from datetime import datetime from itertools import repeat def main(link, counter, start_time): counter.value += 1 print(counter.value, link, start_time) if __name__ == '__main__': manager = Manager() counter = manager.Value('i', 0) start_time = datetime.now() links = ['a','b','c','d', 'e', 'f'] m = 3 with Pool(processes=m) as pool: pool.starmap(main, zip(links, repeat(counter), repeat(start_time))) pool.close() pool.join()
1 a 2019-02-28 12:04:35.360442
2 b 2019-02-28 12:04:35.360442
3 c 2019-02-28 12:04:35.360442
4 d 2019-02-28 12:04:35.360442
5 e 2019-02-28 12:04:35.360442
6 f 2019-02-28 12:04:35.360442
[code python][/code]
Отредактировано PEHDOM (Фев. 28, 2019 12:27:13)
Офлайн
PEHDOMБольшое спасибо за ответ! Можете подсказать как внутри устроены map и starmap? По моим ощущениям, мне кажется, что они заранее разделяют links (из примера) по процессам, а потом каждый процесс обрабатывает ту часть links, которая ему досталась. Это же справедливо и для потоков. Вывод делаю на основе того, что вначале идет быстрая параллельная обработка, а в конце только один один/процесс поток медленно “доделывает” свою часть. Есть ли возможность сделать так, чтобы они действительно разбирали данные по одному элементу, а не заранее делили их на части? Или они уже так делают и у меня проблема в другом?
Офлайн
Room_onmap и starmap работают идентично, разница только в принимаемых аргументах, первый принимает элементы списка и скармливает процессу как есть, а второй распаковывет вложеные списки, и передает уже аргументами.
Можете подсказать как внутри устроены map и starmap?
Room_onОни так и делают, это легко проверить простым кодом, пускай линки кратные трем обрабатываються 1 секунду, кратные двум - три, остальне 7:
По моим ощущениям, мне кажется, что они заранее разделяют links (из примера) по процессам, а потом каждый процесс обрабатывает ту часть links, которая ему досталась. Это же справедливо и для потоков. Вывод делаю на основе того, что вначале идет быстрая параллельная обработка, а в конце только один один/процесс поток медленно “доделывает” свою часть. Есть ли возможность сделать так, чтобы они действительно разбирали данные по одному элементу, а не заранее делили их на части? Или они уже так делают и у меня проблема в другом?
from multiprocessing import Pool, Manager from itertools import repeat import time def main(link, counter): print(time.strftime('%H:%M:%S', time.localtime()), link, ' - start process' ) if link%3==0: time.sleep(1) elif link%2==0: time.sleep(3) else: time.sleep(7) counter.value += 1 print(time.strftime('%H:%M:%S', time.localtime()), link, ' - end process' ) if __name__ == '__main__': manager = Manager() counter = manager.Value('i', 0) links = [1, 2, 3, 4, 5, 6, 7, 8] m = 3 with Pool(processes=m) as pool: pool.starmap(main, zip(links, repeat(counter))) pool.close() pool.join() >>> 21:48:12 1 - start process 21:48:12 2 - start process 21:48:12 3 - start process 21:48:13 3 - end process 21:48:13 4 - start process 21:48:15 2 - end process 21:48:15 5 - start process 21:48:16 4 - end process 21:48:16 6 - start process 21:48:17 6 - end process 21:48:17 7 - start process 21:48:19 1 - end process 21:48:19 8 - start process 21:48:22 8 - end process 21:48:22 5 - end process 21:48:24 7 - end process >>>
[code python][/code]
Отредактировано PEHDOM (Март 4, 2019 22:01:58)
Офлайн