И модули потоковой обработки, и модули многопроцессорности в python стремятся делать одно и то же, а именно выполнять ряд задач одновременно, однако способ, которым этот модуль потоковой обработки выполняет это, и модуль многопроцессорной обработки очень разные.

Прежде чем углубляться в эту тему, лучше всего узнать, что такое поток и что такое процесс: ~

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

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

Разница между потоками и многопроцессорностью: ~

Резьба:

  • В существующем процессе создается новый поток.
  • Запуск потока выполняется быстрее, чем запуск процесса
  • Память распределяется между всеми потоками
  • Мьютексы часто необходимы для управления доступом к общим данным
  • Один GIL (Global Interpreter Lock) для всех потоков (Важно)
  • Он не может делать что-то параллельно, но он может делать что-то одновременно, то есть он может переключаться между делами, когда у него есть время.

Многопроцессорность:

  • Новый процесс запускается независимо от первого процесса
  • Запуск процесса медленнее, чем запуск потока
  • Память не распределяется между процессами (т. Е. При запуске процесса задействуется больше памяти по сравнению с потоком, хотя дочерний процесс получает доступ к памяти родительского процесса)
  • Мьютексы не требуются (кроме случаев, когда потоки в новом процессе, то есть дочерний процесс выполняет потоки)
  • Один GIL (Global Interpreter Lock) для каждого процесса

Что такое GIL (Global Interpreter Lock)

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

На стороне потоковой передачи GIL гарантирует, что интерпретатор python не может делать две вещи одновременно.

Что касается многопроцессорной обработки, GIL - это один для каждого процесса, поэтому вы действительно можете делать две вещи параллельно, потому что у вас есть несколько процессов.

Зачем нам нужен GIL?

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

Когда использовать одно вместо другого?

В многопоточности используется только одно ядро ​​(т. Е. Использование процессора составляет 100–109%, а остальное 0%) из-за GIL, даже если программа может сказать, что все 32 ядра работают, тогда как в многопроцессорной обработке используются все 32 ядра (т. Е. все ядра работают на 100%).

Многопроцессорность

Предположим, у вас есть 2 миллиона записей данных. Что вы могли бы сделать, так это разделить эти данные для каждого ядра, а затем обработать их независимо. Под независимым я подразумеваю, что если у вас 32 ядра, вы можете выполнять 1/32 работы на процесс, а затем вы можете использовать process.join(), чтобы дождаться всех результатов, а затем вы можете агрегировать результаты, и это должно ускорить то, что вы делаете. в 32 раза.

Многопоточность

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

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

Заключение

  • В любой момент времени в процессе Python может быть только один запущенный поток.
  • Многопроцессорность - это параллелизм. Многопоточность - это параллелизм.
  • Многопроцессорность предназначена для увеличения скорости. Многопоточность предназначена для сокрытия задержки.
  • Многопроцессорность лучше всего подходит для вычислений. Многопоточность лучше всего подходит для ввода-вывода.
  • Если у вас тяжелые задачи с ЦП, используйте многопроцессорность с n_process = n_cores и никогда больше. Никогда!
  • Если у вас есть тяжелые задачи ввода-вывода, используйте многопоточность с n_threads = m * n_cores с m числом больше 1, которое вы можете настроить самостоятельно. Попробуйте несколько значений и выберите тот, который дает наилучшее ускорение, потому что общего правила нет. Например, значение по умолчанию m в ThreadPoolExecutor установлено на 5 [Источник], что, честно говоря, кажется мне довольно случайным.