Python несколько процессов одновременно

Подробно про многопроцессорность в Python – модуль multiprocessing

В этой статье мы узнаем, как добиться многопроцессорности с помощью Python и обсудим его передовые концепции.

Что такое многопроцессорность в Python?

Многопроцессорность в Python – это способность системы запускать несколько процессов параллельно. Проще говоря, многопроцессорность использует два или более ЦП в одной компьютерной системе. Этот метод также может распределять задачи между процессами.

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

Python предоставляет встроенный пакет, называемый multiprocessing, который поддерживает процессы подкачки. Прежде чем работать с многопроцессорной обработкой, мы должны ознакомиться с объектом процесса.

Зачем нужна многопроцессорность?

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

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

Следовательно, многопроцессорность необходима для выполнения нескольких задач одновременно без прерывания. Это также позволяет легко отслеживать все задачи. Вот почему важна необходимость концепции многопроцессорности:

  • Многопроцессорность можно представить как компьютер с более чем одним центральным процессором.
  • Многоядерный процессор относится к одному вычислительному компоненту с двумя или более независимыми блоками.

В многопроцессорном режиме ЦП может назначать несколько задач, каждая из которых имеет свой собственный процессор.

Модуль многопроцессорности в Python

Python предоставляет модуль многопроцессорности для выполнения нескольких задач в одной системе. Он предлагает удобный и интуитивно понятный API для работы с многопроцессорной обработкой.

Давайте разберемся на простом примере множественной обработки.

from multiprocessing import Process def disp(): print ('Hello !! Welcome to Python Tutorial') if __name__ == '__main__': p = Process(target=disp) p.start() p.join()
'Hello !! Welcome to Python Tutorial'

В приведенном выше коде мы импортировали класс Process, а затем создали объект Process в функции disp(). Затем мы запустили процесс с помощью метода start() и завершили процесс с помощью метода join(). Мы также можем передавать аргументы в объявленную функцию, используя ключевые слова args.

Давайте разберемся в следующем примере многопроцессорной обработки с аргументами.

# Python multiprocessing example # importing the multiprocessing module import multiprocessing def cube(n): # This function will print the cube of the given number print("The Cube is: <>".format(n * n * n)) def square(n): # This function will print the square of the given number print("The Square is: <>".format(n * n)) if __name__ == "__main__": # creating two processes process1 = multiprocessing.Process(target= square, args=(5, )) process2 = multiprocessing.Process(target= cube, args=(5, )) # Here we start the process 1 process1.start() # Here we start process 2 process2.start() # The join() method is used to wait for process 1 to complete process1.join() # It is used to wait for process 1 to complete process2.join() # Print if both processes are completed print("Both processes are finished")
The Cube is: 125 The Square is: 25 Both processes are finished

В приведенном выше примере мы создали две функции: функция cube() вычисляет куб данного числа, а функция square() вычисляет квадрат данного числа.

Читайте также:  Javascript get input file data

Затем мы определили объект процесса класса Process, который имеет два аргумента. Первый аргумент – это target, который представляет функцию, которая должна быть выполнена, а второй аргумент – это args, который представляет аргумент, который должен быть передан внутри функции.

process1 = multiprocessing.Process(target= square, args=(5, )) process2 = multiprocessing.Process(target= cube, args=(5, ))

Мы использовали метод start(), чтобы запустить процесс.

process1.start() process2.start()

Как видно из выходных данных, он ожидает завершения первого процесса, а затем второго процесса. Последний оператор выполняется после завершения обоих процессов.

Классы многопроцессорной обработки Python

Модуль многопроцессорности Python предоставляет множество классов, которые обычно используются для построения параллельных программ. Мы обсудим его основные классы – Process, Queue и Lock. Мы уже обсуждали класс Process в предыдущем примере. Теперь обсудим классы Queue и Lock.

Давайте посмотрим на простой пример нахождения числа CPU, работающих в настоящее время в системе.

import multiprocessing print("The number of CPU currently working in system : ", multiprocessing.cpu_count())
('The number of CPU currently woking in system : ', 32)

Вышеуказанное количество CPU может различаться для вашего компьютера. У нас количество ядер 32.

Использование класса Queue

Мы знаем, что Queue – важная часть структуры данных. Многопроцессорность Python в точности такая же, как и очередь структуры данных, основанная на концепции «первым пришел – первым ушел». Очередь в Python обычно хранит объект и играет важную роль в обмене данными между процессами.

Queue передаются как параметр в целевой функции процесса, чтобы позволить процессу потреблять данные. Queue предоставляет функцию put() для вставки данных и функцию get() для получения данных из очередей. Рассмотрим следующий пример.

# Importing Queue Class from multiprocessing import Queue fruits = ['Apple', 'Orange', 'Guava', 'Papaya', 'Banana'] count = 1 # creating a queue object queue = Queue() print('pushing items to the queue:') for fr in fruits: print('item no: ', count, ' ', fr) queue.put(fr) count += 1 print('\npopping items from the queue:') count = 0 while not queue.empty(): print('item no: ', count, ' ', queue.get()) count += 1
pushing items to the queue: ('item no: ', 1, ' ', 'Apple') ('item no: ', 2, ' ', 'Orange') ('item no: ', 3, ' ', 'Guava') ('item no: ', 4, ' ', 'Papaya') ('item no: ', 5, ' ', 'Banana') popping items from the queue: ('item no: ', 0, ' ', 'Apple') ('item no: ', 1, ' ', 'Orange') ('item no: ', 2, ' ', 'Guava') ('item no: ', 3, ' ', 'Papaya') ('item no: ', 4, ' ', 'Banana')

В приведенном выше коде мы импортировали класс Queue и инициализировали список с именем fruit. Затем мы присвоили счетчик 1. Переменная счетчика будет подсчитывать общее количество элементов. Затем мы создали объект очереди, вызвав метод Queue(). Этот объект будет использоваться для выполнения операций в Queue. В цикле for мы вставляли элементы один за другим в очередь с помощью функции put() и увеличивали счетчик на 1 с каждой итерацией цикла.

Читайте также:  Справочник по java команды

Класс блокировки

Класс multiprocessing Lock используется для получения блокировки процесса, чтобы мы могли удерживать другой процесс для выполнения аналогичного кода до тех пор, пока блокировка не будет снята. Класс Lock выполняет в основном две задачи. Первая – получить блокировку с помощью функции accept(), а вторая – снять блокировку с помощью функции release().

Пример многопроцессорной обработки

Предположим, у нас есть несколько задач. Итак, мы создаем две очереди: первая очередь будет обслуживать задачи, а другая будет хранить полный журнал задач. Следующим шагом является создание экземпляров процессов для выполнения задачи. Как обсуждалось ранее, класс Queue уже синхронизирован, поэтому нам не нужно получать блокировку с помощью класса Lock.

Мы объединим все классы многопроцессорной обработки вместе. Давайте посмотрим на пример ниже.

from multiprocessing import Lock, Process, Queue, current_process import time import queue def jobTodo(tasks_to_perform, complete_tasks): while True: try: # The try block to catch task from the queue. # The get_nowait() function is used to # raise queue.Empty exception if the queue is empty. task = tasks_to_perform.get_nowait() except queue.Empty: break else: # if no exception has been raised, the else block will execute # add the task completion print(task) complete_tasks.put(task + ' is done by ' + current_process().name) time.sleep(.5) return True def main(): total_task = 8 total_number_of_processes = 3 tasks_to_perform = Queue() complete_tasks = Queue() number_of_processes = [] for i in range(total_task): tasks_to_perform.put("Task no " + str(i)) # defining number of processes for w in range(total_number_of_processes): p = Process(target=jobTodo, args=(tasks_to_perform, complete_tasks)) number_of_processes.append(p) p.start() # completing process for p in number_of_processes: p.join() # print the output while not complete_tasks.empty(): print(complete_tasks.get()) return True if __name__ == '__main__': main()
Task no 2 Task no 5 Task no 0 Task no 3 Task no 6 Task no 1 Task no 4 Task no 7 Task no 0 is done by Process-1 Task no 1 is done by Process-3 Task no 2 is done by Process-2 Task no 3 is done by Process-1 Task no 4 is done by Process-3 Task no 5 is done by Process-2 Task no 6 is done by Process-1 Task no 7 is done by Process-3

Пул многопроцессорности

Пул многопроцессорности Python необходим для параллельного выполнения функции с несколькими входными значениями. Он также используется для распределения входных данных по процессам (параллелизм данных). Рассмотрим следующий пример многопроцессорного пула.

from multiprocessing import Pool import time w = (["V", 5], ["X", 2], ["Y", 1], ["Z", 3]) def work_log(data_for_work): print(" Process name is %s waiting time is %s seconds" % (data_for_work[0], data_for_work[1])) time.sleep(int(data_for_work[1])) print(" Process %s Executed." % data_for_work[0]) def handler(): p = Pool(2) p.map(work_log, w) if __name__ == '__main__': handler()
Process name is V waiting time is 5 seconds Process V Executed. Process name is X waiting time is 2 seconds Process X Executed. Process name is Y waiting time is 1 seconds Process Y Executed. Process name is Z waiting time is 3 seconds Process Z Executed.

Давайте разберемся с еще одним примером многопроцессорного пула.

from multiprocessing import Pool def fun(x): return x*x if __name__ == '__main__': with Pool(5) as p: print(p.map(fun, [1, 2, 3]))

Прокси-объекты

Прокси-объекты называются общими объектами, которые находятся в другом процессе. Этот объект также называется прокси. У нескольких прокси-объектов может быть похожий референт. Прокси-объект состоит из различных методов, которые используются для вызова соответствующих методов его референта. Ниже приведен пример прокси-объектов.

from multiprocessing import Manager manager = Manager() l = manager.list([i*i for i in range(10)]) print(l) print(repr(l)) print(l[4]) print(l[2:5])
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 16 [4, 9, 16]

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

Читайте также:  Изменение элементов массива python

Часто используемые функции для достижения многопроцессорности

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

Метод Описание
pipe() Функция pipe() возвращает пару объектов подключения.
run() Метод run() используется для представления действий процесса.
start() Метод start() используется для запуска процесса.
join() ([timeout]) Метод join() используется для блокировки процесса до тех пор, пока не завершится процесс, каким метод join() вызван. Timeout – необязательный аргумент.
is_alive() Возвращается, если процесс действующий.
terminate() Как следует из названия, используется для завершения процесса. Всегда помните – в Linux используется метод terminate(), для Windows мы используем метод TerminateProcess().
kill() Этот метод аналогичен terminate(), но использует сигнал SIGKILL в Unix.
close() Используется для закрытия объекта Process и освобождения всех связанных с ним ресурсов.
qsize () Возвращает приблизительный размер очереди.
empty() Если очередь пуста, возвращается True.
full() Возвращает True, если очередь заполнена.
get_await () Этот метод эквивалентен get (False).
get() Используется для получения элементов из очереди. Удаляет и возвращает элемент из очереди.
put() Этот метод используется для вставки элемента в очередь.
cpu_count() Возвращает количество работающих ЦП в системе.
current_process() Он возвращает объект Process, соответствующий текущему процессу.
parent_process() Он возвращает родительский объект Process, соответствующий текущему процессу.
task_done() Эта функция используется для указания того, что поставленная в очередь задача завершена.
join_thread() Этот метод используется для присоединения к фоновому потоку.

Источник

Оцените статью