Ответ
Многопроцессорность (multiprocessing) — это подход к параллельному выполнению задач, при котором операционная система запускает несколько независимых процессов. Каждый процесс имеет собственное адресное пространство памяти, свои ресурсы CPU и не разделяет состояние с другими процессами.
Цель многопроцессорности:
Основная цель — достижение истинного параллелизма, позволяющего эффективно использовать все доступные ядра процессора для выполнения CPU-bound задач (задач, ограниченных вычислительной мощностью процессора, например, сложные расчеты, обработка изображений).
Отличие от многопоточности:
В отличие от потоков (threads), которые выполняются в рамках одного процесса и разделяют его память, процессы полностью изолированы. Это обеспечивает:
- Изоляцию памяти: Отсутствие общих данных по умолчанию исключает проблемы с состоянием и race conditions, характерные для многопоточности.
- Устойчивость: Сбой одного процесса не приводит к краху всей программы, так как другие процессы продолжают работать независимо.
Многопроцессорность в Python:
В Python модуль multiprocessing
позволяет создавать и управлять процессами. Он является ключевым для обхода ограничения Global Interpreter Lock (GIL), которое препятствует истинному параллелизму в многопоточных приложениях на одном интерпретаторе Python. Каждый процесс запускает свой собственный интерпретатор Python, тем самым обходя GIL.
Пример использования multiprocessing
:
from multiprocessing import Process, current_process
import os
import time
def worker(name: str):
"""Функция, выполняемая в отдельном процессе."""
print(f"Процесс {name} (PID: {os.getpid()}) начал работу.")
time.sleep(2) # Имитация выполнения CPU-bound задачи
print(f"Процесс {name} (PID: {os.getpid()}) завершил работу.")
if __name__ == '__main__':
print(f"Главный процесс (PID: {os.getpid()}) начал работу.")
processes = []
for i in range(3):
# Создаем новый процесс, указывая целевую функцию и аргументы
p = Process(target=worker, args=(f'Worker-{i}',))
processes.append(p)
p.start() # Запускаем процесс
# Ожидаем завершения всех дочерних процессов
for p in processes:
p.join()
print(f"Главный процесс (PID: {os.getpid()}) завершил работу.")
Преимущества:
- Истинный параллелизм: Эффективное использование всех доступных ядер процессора для CPU-bound задач.
- Изоляция: Каждый процесс имеет свою память, что исключает проблемы с состоянием и race conditions.
- Устойчивость: Сбой одного процесса не влияет на другие, повышая общую надежность системы.
Недостатки:
- Накладные расходы: Создание и управление процессами требует больше ресурсов (памяти, времени CPU) по сравнению с потоками.
- Обмен данными: Обмен данными между процессами сложнее и требует специальных механизмов (например,
Queue
,Pipe
,Value
,Array
из модуляmultiprocessing
). - Не подходит для I/O-bound задач: Для задач, ограниченных вводом/выводом (сеть, диск), асинхронное программирование или многопоточность часто более эффективны из-за меньших накладных расходов.