Многозадачность стала проще благодаря примерам Python
Многопоточность и многопроцессорность — два способа достижения многозадачности (подумайте о распределенных вычислениях!) в Python. Многозадачность полезна при параллельном выполнении функций и кода, например при разбиении математических вычислений на несколько более мелких частей или разделении элементов в цикле for, если они независимы друг от друга. другой. В этой статье будут представлены и сравнены различия между многопоточностью и многопроцессорностью, когда использовать каждый метод и как их реализовать в Python.
Обновление: эта статья является частью серии. Ознакомьтесь с другими темами за 10 минут здесь!
Оглавление
- Многопоточность против многопроцессорности
- Многопоточность как функция Python
- Многопоточность как класс Python
- Многопроцессорность как функция Python
Многопоточность против многопроцессорности
По формальному определению многопоточность относится к способности процессора одновременно выполнять несколько потоков, при этом каждый поток запускает процесс. Принимая во внимание, что многопроцессорностьотносится к способности системы одновременно запускать несколько процессоров, где каждый процессор может запускать один или несколько потоков.
Из приведенной выше диаграммы видно, что при многопоточности (средняя диаграмма) несколько потоков совместно используют один и тот же код, данные и файлы, но работают в разных регистрах и стеках. Многопроцессорность (правая диаграмма) умножает один процессор — реплицируя код, данные и файлы, что влечет за собой дополнительные накладные расходы.
Многопоточность полезна для процессов, связанных с вводом-выводом, таких как чтение файлов из сети или базы данных, поскольку каждый поток может одновременно выполнять процесс, связанный с вводом-выводом. Многопроцессорность полезна для процессов, привязанных к ЦП, таких как задачи, требующие больших вычислительных ресурсов, поскольку она выигрывает от наличия нескольких процессоров; подобно тому, как многоядерные компьютеры работают быстрее, чем компьютеры с одним ядром.
Обратите внимание, что использование многопоточности для процессов, привязанных к ЦП, может снизить производительность из-за конкурирующих ресурсов, которые гарантируют, что только один поток может выполняться одновременно, и возникают накладные расходы при работе с несколькими потоками.
С другой стороны, многопроцессорность может использоваться для процессов, связанных с вводом-выводом. Однако накладные расходы на управление несколькими процессами выше, чем на управление несколькими потоками, как показано выше. Вы можете заметить, что многопроцессорность может привести к более высокой загрузке ЦП из-за того, что программа использует несколько ядер ЦП, что и ожидается.
Многопоточность как функция Python
Многопоточность может быть реализована с помощью встроенной библиотеки Python threading
и выполняется в следующем порядке:
- Создать поток: каждый поток должен быть помечен функцией Python с ее аргументами.
- Начать выполнение задачи
- Подождите, пока поток завершит выполнение: полезно для обеспечения завершения или «контрольных точек».
В приведенном ниже фрагменте кода реализованы описанные выше шаги вместе с блокировкой потока (строка 22) для обработки конкурирующих ресурсов, что в нашем случае необязательно.
Есть несколько примечательных наблюдений
- Строка 12–15: процессы выполняются в разных потоках (идентификатор потока), но с одним и тем же процессором (идентификатор процесса).
- Строка 8: Если бы вместо этого было реализовано
time.sleep(sleep_duration)
между получением и освобождением блокировки, потоки будут выполняться последовательно, и не будет никакой экономии времени — вы можете попробовать!
Многопоточность как класс Python
Для пользователей, предпочитающих объектно-ориентированное программирование, многопоточность может быть реализована в виде класса Python, наследуемого от суперкласса threading.Thread
. Одним из преимуществ использования классов вместо функций будет возможность совместного использования переменных через объекты класса.
Разница между реализацией многопоточности как функции и класса будет заключаться в шаге 1 (создание потока), поскольку теперь поток помечается методом класса, а не функцией. Последующие шаги для вызова t1.start()
и t1.join()
остаются прежними.
import time class Sleep(threading.Thread): def __init__(self, sleep_duration): self.sleep_duration = sleep_duration def sleep(self): time.sleep(self.sleep_duration) if __name__ == "__main__": # Create thread sleep_class = Sleep(2) t1 = threading.Thread(target=sleep_class.sleep)
Многопроцессорность как функция Python
Многопроцессорность может быть реализована с помощью встроенной библиотеки Python multiprocessing
с использованием двух разных методов — Process и Pool.
Метод Process подобен описанному выше многопоточному методу, в котором каждый процесс помечается функцией со своими аргументами. В приведенном ниже фрагменте кода мы видим, что многопроцессорная обработка занимает больше времени, чем многопоточность, поскольку при работе с несколькими процессорами больше накладных расходов.
Пулметод позволяет пользователям определять количество рабочих процессов и распределять все процессы по доступным процессорам по расписанию «первым поступил — первым обслужен», автоматически обрабатывая планирование процессов. Метод пула используется для разбиения функции на несколько небольших частей с использованием map
или starmap
(строка 19) — запуск одной и той же функции с разными входными аргументами. В то время как метод Process используется для запуска различных функций.
Надеюсь, что эта статья представила концепцию многопоточности и многопроцессорности, а также когда использовать каждый метод. Примеры Python — это скелетные фрагменты кода, которые вы можете заменить своими функциями, и все готово!
Спасибо за прочтение! Если вам понравилась эта статья, поделитесь ею.
Ссылки по теме
threading
Документация по Python: https://docs.python.org/3/library/threading.html
multiprocessing
Документация по Python: https://docs.python.org/3/library/multiprocessing.html