Сегодня в этой статье по Python мы увидим многопроцессорную работу с Python. Кроме того, мы рассмотрим пакет и структуру многопроцессорной обработки в Python. Кроме того, мы обсудим класс процесса в Python Multiprocessing, а также получим информацию о процессе. Чтобы это произошло, мы заимствуем несколько методов из модуля многопоточности. Наряду с этим мы изучим блокировку и пул класса Python Multiprocessing.
Итак, давайте начнем.
Сначала поговорим о параллельной обработке. Это способ одновременно разбивать и запускать программные задачи на нескольких микропроцессорах. По сути, это попытка сократить время обработки и это то, чего мы можем достичь с помощью компьютера с двумя или более процессорами или с использованием компьютерной сети. Мы также называем это параллельными вычислениями.
Итак, теперь перейдем к Python Multiprocessing, это способ повысить производительность путем создания параллельного кода. Производители процессоров делают это возможным, добавляя больше ядер к своим процессорам. В многопроцессорной системе приложения разбиваются на более мелкие подпрограммы для самостоятельной работы. Взгляните на однопроцессорную систему. Учитывая несколько процессов одновременно, он пытается прерывать и переключаться между задачами. Как бы вы себя чувствовали, будучи единственным шеф-поваром на кухне с сотнями клиентов? Вы должны были бы выполнять все обычные задачи от выпечки до замеса теста.
Многопроцессорная обработка в Python – это пакет, который мы можем использовать с Python для порождения процессов с использованием API, который очень похож на модуль потоков . Благодаря поддержке как локального, так и удаленного параллелизма, он позволяет программисту эффективно использовать несколько процессоров на данном компьютере. Прежде чем мы сможем объяснить вам это, давайте рассмотрим пример пула – объекта, способа распараллеливания выполнения функции по входным значениям и распределения входных данных по процессам. Это параллелизм данных (создайте из этого модуль и запустите его):
from multiprocessing import Pool def f(x): return x*x with Pool(5) as p: print(p.map(f,[1,2,3]))
Хотите узнать, сколько ядер у вашей машины? Попробуйте метод cpu_count().
>> import multiprocessing >>> multiprocessing.cpu_count()
Так из чего состоит такая система? У нас есть следующие возможности:
В любом случае, процессор может выполнять несколько задач одновременно, назначая процессор для каждой задачи.
Давайте сначала поговорим о классе Process в Python Multiprocessing. Это абстракция для настройки другого процесса, позволяющая родительскому приложению контролировать выполнение. Здесь мы наблюдаем методы start() и join(). Давайте сначала возьмем пример.
import multiprocessing from multiprocessing import Process def testing(): print("Объектов") def square(n): print("Число квадратов в ",n**2) def cube(n): print("Количество кубиков в ",n**3) if __name__=="__main__": p1=Process(target=square,args=(7,)) p2=Process(target=cube,args=(7,)) p3=Process(target=testing) p1.start() p2.start() p3.start() p1.join() p2.join() p3.join() print("Мы закончили")
Мы сохранили на нашем рабочем столе, а затем дважды запустили из командной строки.
Давайте разберемся с этим фрагментом кода. Process() позволяет нам создать экземпляр класса Process. start() говорит Python начать обработку. Но тогда, если мы позволим этому быть, это потребляет ресурсы, и мы можем исчерпать их в более поздний момент времени. Это потому, что он позволяет процессу оставаться бездействующим и не завершаться. Чтобы избежать этого, мы вызываем метод join(). При этом нам не нужно убивать их вручную. Присоединение останавливает выполнение текущей программы до завершения процесса. Это гарантирует, что программа ожидает завершения p1 и затем завершения p2. Затем он выполняет следующие операторы программы. И последнее: аргумент ключевого слова args позволяет нам указать значения передаваемого аргумента. Кроме того, цель позволяет нам выбрать функцию для выполнения процесса.
Мы можем захотеть получить ID процесса или одного из его дочерних элементов. Мы также можем захотеть узнать, жив ли он еще. Следующая программа демонстрирует эту функциональность:
import multiprocessing from multiprocessing import Process import os def child1(): print("Child 1",os.getpid()) def child2(): print("Child 2",os.getpid()) if __name__=="__main__": print("Parent ID",os.getpid()) p1=Process(target=child1) p2=Process(target=child2) p1.start() p2.start() p1.join() alive='Yes' if p1.is_alive() else 'No' print("Is p1 alive?",alive) alive='Yes' if p2.is_alive() else 'No' print("Is p2 alive?",alive) p2.join() print("Мы закончили")
В многопроцессорной среде Python каждый процесс занимает свое собственное пространство памяти для запуска независимо. Завершается, когда целевая функция завершается выполнением.
Мы также можем установить имена для процессов, чтобы мы могли получить их, когда захотим. Это сделано для того, чтобы сделать его более читабельным.
import multiprocessing from multiprocessing import Process, current_process import os def child1(): print(current_process().name) def child2(): print(current_process().name) if __name__=="__main__": print("Parent ID",os.getpid()) p1=Process(target=child1,name='Child 1') p2=Process(target=child2,name='Child 2') p1.start() p2.start() p1.join() p2.join() print("Мы закончили")
Как видите, метод current_process() дает нам имя процесса, который вызывает нашу функцию. Посмотрите, что происходит, когда мы не присваиваем имя одному из процессов:
import multiprocessing from multiprocessing import Process, current_process import os def child1(): print(current_process().name) def child2(): print(current_process().name) if __name__=="__main__": print("Parent ID",os.getpid()) p1=Process(target=child1) p2=Process(target=child2,name='Child 2') p1.start() p2.start() p1.join() p2.join() print("Мы закончили")
Что ж, модуль многопроцессорной обработки Python присваивает номер каждому процессу как часть его имени, когда мы этого не делаем.
Как и многопоточный модуль, многопроцессорная обработка в Python поддерживает блокировки. Процесс включает в себя импорт Lock, его использование, выполнение чего-либо, а затем освобождение. Давайте взглянем.
В следующем фрагменте кода мы заставляем процесс получить блокировку, пока он выполняет свою работу.
from multiprocessing import Process, Lock lock=Lock() def printer(item): lock.acquire() try: print(item) finally: lock.release() if __name__=="__main__": items=['nacho','salsa',7] for item in items: p=Process(target=printer,args=(item,))
p.start()
Давайте запустим этот код трижды, чтобы увидеть, какие разные результаты мы получаем.
Блокировка не позволяет потокам мешать друг другу. Следующий процесс ожидает снятия блокировки, прежде чем продолжить.
Этот класс представляет пул рабочих процессов; его методы позволяют переложить задачи на такие процессы. Давайте рассмотрим пример (Создайте модуль и запустите его).
from multiprocessing import Pool def double(n): return n*2 if __name__=='__main__': nums=[2,3,6] pool=Pool(processes=3) print(pool.map(double,nums))
Мы создаем экземпляр пула и создаем процесс с 3 работниками. map() отображает функцию double и повторяемость для каждого процесса.
Другой метод, который возвращает нам результаты наших процессов в пуле, – это метод apply_async().
from multiprocessing import Pool def double(n): return n*2 if __name__=='__main__': pool=Pool(processes=3) result=pool.apply_async(double,(7,)) print(result.get(timeout=1))
Итак, все это было в многопроцессорной обработке Python. Надеюсь, вам понравится наше объяснение.
В этой статье по многопроцессорности Python мы обсудили полную концепцию многопроцессорности в Python. Кроме того, мы рассмотрели пул многопроцессорных процессов Python, блокировку и процессы. Теперь у вас есть представление о том, как использовать ваши процессоры в полной мере.