Многопроцессорная обработка Python - как сделать ее более эффективной - PullRequest
1 голос
/ 17 марта 2019

Рассмотрим следующие две короткие программы.

normal_test.py :

import time

if __name__ == '__main__':
    t_end = time.time() + 1
    loop_iterations = 0
    while time.time() < t_end:
        loop_iterations += 1

    print(loop_iterations)

Вывод (на моем компьютере):

4900677

mp_test.py :

from multiprocessing import Process
from multiprocessing import Manager
import time


def loop1(ns):
    t_end = time.time() + 1
    while time.time() < t_end:
        ns.loop_iterations1 += 1


def loop2(ns):
    t_end = time.time() + 1
    while time.time() < t_end:
        ns.loop_iterations2 += 1


if __name__ == '__main__':
    manager = Manager()
    ns = manager.Namespace()
    ns.loop_iterations1 = 0
    ns.loop_iterations2 = 0

    p1 = Process(target=loop1, args=(ns,))
    p2 = Process(target=loop2, args=(ns,))
    p1.start()
    p2.start()

    p1.join()
    p2.join()

    print(ns.loop_iterations1)
    print(ns.loop_iterations2)

Вывод (на моей машине):

5533
5527

Янадеясь использовать многопроцессорную обработку Python на Raspberry Pi для параллельного чтения значений из нескольких АЦП.Таким образом, скорость важна.Ноутбук, на котором я запускал эти две программы, имеет четыре ядра, поэтому я не могу понять, почему процессы, созданные во второй программе, способны выполнять почти в 900 раз меньше итераций, чем один процесс в первой программе.Я неправильно использую многопроцессорную библиотеку Python?Как я могу ускорить процесс?

1 Ответ

2 голосов
/ 18 марта 2019

Я неправильно использую многопроцессорную библиотеку Python?

Некорректно? Нет. Неэффективно? Да.

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

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

Объект Manager - это общая оболочка многопроцессорной обработки Python для совместного использования. Помещение переменных в диспетчер Namespace означает , что они являются общими, поэтому автоматически проверяйте их перед использованием . (Точнее, они хранятся в одном месте - в одном процессе - и доступны или изменяются из других через прокси.)

Здесь вы сделали метафорический эквивалент замены «Боб: считать так быстро, как вы можете» на «Боб: постоянно прерывать Алису, чтобы спросить, считает ли она, затем считать; Алиса: считать, но Боб постоянно прерывал ее. " Боб и Алиса теперь проводят большую часть своего времени, разговаривая друг с другом, а не считая.

Как документация гласит :

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

(начинается с фразы «как упомянуто выше», но выше не упоминается!).

Существует множество стандартных приемов, таких как пакетная обработка для выполнения большой работы между обменом событиями или использование общей памяти для ускорения совместное использование - но с общей памятью вы вводите необходимость блокировать элементов.

...