Это немного запутанная тема, если вы знакомы с потоками и mprocessing в C/C++/Java, поэтому я надеюсь, что после прочтения это станет для вас ясным.

Несколько реализаций Python?

Python имеет разные реализации на протяжении многих лет. Наиболее часто используется CPython, который реализуется разработчиками ядра Python и сообществом Python при поддержке Python Software Foundation. Именно эту версию вы можете скачать с www.python.org. Очевидно, что CPython реализован на C.

Так что же такое CPython?

https://stackoverflow.com/questions/17130975/python-vs-cpython

@Chiel из Stackoverflow

CPython — это оригинальная реализация Python. Это реализация, которую вы загружаете с Python.org. Люди называют его CPython, чтобы отличить его от других, более поздних реализаций Python, а также отличить реализацию механизма языка от самого языка программирования Python.

Последняя часть - это то, откуда исходит ваше замешательство; вам нужно отделить Python-язык от того, что запускает код Python.

CPython случайно реализован на языке C. На самом деле это всего лишь деталь реализации. CPython компилирует ваш код Python в байт-код (прозрачно) и интерпретирует этот байт-код в цикле оценки.

CPython также первым реализовал новые функции; Разработка на языке Python использует CPython в качестве основы; следуют другие реализации.

Существуют и другие реализации Python, такие как реализации Jython (Java), C# Python и R Python, которые также используются в некоторых областях в сообществе разработчиков Python. Обратите внимание, что So CPython не переводит ваш код Python на C сам по себе. . Вместо этого он запускает цикл интерпретатора. Если вы заинтересованы в этом, ищите Cython, который является совершенно другим зверем.

В CPython реализован специальный механизм, который называется GIL.

Что такое GIL, также известный как Global Interpreter Lock?

В CPython глобальная блокировка интерпретатора или GIL — это мьютекс, который защищает доступ к объектам Python, предотвращая одновременное выполнение байт-кодов Python несколькими потоками. Эта блокировка необходима главным образом потому, что управление памятью CPython не является потокобезопасным. (Однако с тех пор, как существует GIL, другие функции стали зависеть от гарантий, которые он обеспечивает.)

Это решение разработчика/реализатора, которое заключается в том, чтобы не возиться с управлением памятью. Поскольку это действительно большая часть всего устаревшего кода Python, изменить его в любой момент совершенно невозможно (отсюда и идея других реализаций). Что GIL в двух словах означает, что ваши так называемые многопоточные операции в Python на самом деле не являются многопоточными? За исключением некоторых блокирующих и долго работающих приложений, таких как (ввод-вывод, обработка изображений, Numpy, которые происходят вне GIL), большая часть вашего интерпретируемого кода станет узким местом с GIL. Устранение GIL — одна из самых востребованных функций для почтовых групп Python, но разработчикам еще предстоит найти решение по этому поводу. Подробнее об этом https://wiki.python.org/moin/GlobalInterpreterLock

Так какой тогда смысл в потоках в Python?

Потоки, хотя и не так эффективно, как их фактическая цель, и реализация на других языках, по-прежнему являются полезным инструментом для разработчиков, если у вас есть подходящий случай для его использования. Сетевые сценарии, ввод-вывод, задачи, связанные с данными, по-прежнему зависят от ожидания данных, и вы по-прежнему можете выполнять другие вычисления в ЦП, пока они выполняют свою работу, не создавая для них новый процесс (что экономит память и время = производительность для вас). Для процессов с интенсивным использованием ЦП использование модуля потоков малоэффективно.

Когда использовать многопроцессорную обработку и когда использовать потоки

Новый поток порождается из существующего процесса, процесс не зависит от процесса, который он создал. Таким образом, создание потоков c происходит быстрее по сравнению с многопроцессорной обработкой. Вы получите, что вся память используется совместно с потоками, что может быть полезно и эффективно, если этого требуют ваши задачи. Вам понадобится мьютекс с потоками для управления стеком общей памяти, он не нужен для мультипроцессов, у них есть свои собственные области памяти. Один GIL для всех потоков (библиотека потоков), один GIL для каждого процесса (многопроцессорность)

Эти фрагменты кода от Engineer-Man свяжут их в конце страницы.

# threading example
from threading import Thread
import os
import math

def calc():
	for i in range(0, 4000000):
		math.sqrt(i)

threads = []

for i in range(os.cpu_count()):
	print('registering thread %d' % i)
	threads.append(Thread(target=calc))

for thread in threads:
	thread.start()

for thread in threads:
	thread.join()

Как это выглядит при выполнении

# multi processing example
from multiprocessing import Process
import os
import math

def calc():
	for i in range(0, 70000000):
		math.sqrt(i)

processes = []

for i in range(os.cpu_count()):
	print('registering process %d' % i)
	processes.append(Process(target=calc))

for process in processes:
	process.start()

for process in processes:
	process.join()

Как это выглядит при выполнении

Итак, если вы собираетесь использовать ввод-вывод, извлечение данных и сетевые сценарии, определенно используйте потоки с python, если вы собираетесь выполнять всю свою обработку внутри ЦП, тогда я предлагаю использовать многопроцессорность для вашей программы.

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

Например, https://github.com/engineer-man/youtube/tree/master/036.



Спасибо за чтение и всем удачного кодирования!