Может ли python работать на нескольких ядрах?
Вопрос: из-за использования python для "GIL" есть python, способный одновременно работать с отдельными потоками?
информация:
После прочтения этого я довольно не уверен в том, способен ли python использовать многоядерный процессор. Как и в случае с python, очень странно думать, что у него не будет таких мощных способностей. Поэтому, чувствуя себя не уверенным, я решил спросить здесь. Если я пишу программу с несколькими потоками, будет ли она работать одновременно на нескольких ядрах?
Ответы
Ответ 1
Ответ: "Да, но..."
Но cPython не может, когда вы используете обычные потоки для concurrency.
Вы можете использовать что-то вроде multiprocessing
, celery
или mpi4py
, чтобы разделить параллельную работу на другой процесс;
Или вы можете использовать что-то вроде Jython или IronPython, чтобы использовать альтернативный интерпретатор, который не имеет GIL.
Более мягкое решение - использовать библиотеки, которые не запускают GIL для тяжелых задач ЦП, например numpy
могут выполнять тяжелый подъем, а не сохраняя GIL, поэтому могут продолжаться другие потоки python. Таким образом вы также можете использовать библиотеку ctypes
.
Если вы не выполняете работу с ЦП, вы можете полностью игнорировать проблему GIL (вид), так как python не будет использовать GIL, пока он ждет ввода-вывода.
Ответ 2
Python threads не может использовать преимущества многих ядер. Это связано с внутренней деталью реализации, называемой GIL (глобальная блокировка интерпретатора) в реализации C python (cPython), которая почти наверняка используется вами.
Обходной путь - это multiprocessing
модуль http://www.python.org/dev/peps/pep-0371/, который был разработан для этой цели.
Документация: http://docs.python.org/library/multiprocessing.html
(Или используйте параллельный язык.)
Ответ 3
CPython (классическая и распространенная реализация Python) не может иметь более одного потока, исполняющего байт-код Python в одно и то же время. Это означает, что программы, связанные с вычислением, будут использовать только одно ядро. Операции ввода-вывода и вычисления, происходящие внутри C-расширений (например, numpy), могут работать одновременно.
Другая реализация Python (например, Jython или PyPy) может вести себя по-другому, я менее четко понимаю их детали.
Обычно рекомендуется использовать многие процессы, а не многие потоки.
Ответ 4
Потоки разделяют процесс, и процесс выполняется на ядре, но вы можете использовать модуль многопроцессорности python для вызова ваших функций в отдельных процессах и использования других ядер, или вы можете использовать модуль подпроцесса, который может запускать ваш код и не- питон кода.
Ответ 5
пример кода, который принимает все 4 ядра на моем ubuntu 14.04, python 2.7 64 бит.
import time
import threading
def t():
with open('/dev/urandom') as f:
for x in xrange(100):
f.read(4 * 65535)
if __name__ == '__main__':
start_time = time.time()
t()
t()
t()
t()
print "Sequential run time: %.2f seconds" % (time.time() - start_time)
start_time = time.time()
t1 = threading.Thread(target=t)
t2 = threading.Thread(target=t)
t3 = threading.Thread(target=t)
t4 = threading.Thread(target=t)
t1.start()
t2.start()
t3.start()
t4.start()
t1.join()
t2.join()
t3.join()
t4.join()
print "Parallel run time: %.2f seconds" % (time.time() - start_time)
результат:
$ python 1.py
Sequential run time: 3.69 seconds
Parallel run time: 4.82 seconds
Ответ 6
Я преобразовал скрипт в Python3 и запустил его на своем Raspberry Pi 3B+:
import time
import threading
def t():
with open('/dev/urandom', 'rb') as f:
for x in range(100):
f.read(4 * 65535)
if __name__ == '__main__':
start_time = time.time()
t()
t()
t()
t()
print("Sequential run time: %.2f seconds" % (time.time() - start_time))
start_time = time.time()
t1 = threading.Thread(target=t)
t2 = threading.Thread(target=t)
t3 = threading.Thread(target=t)
t4 = threading.Thread(target=t)
t1.start()
t2.start()
t3.start()
t4.start()
t1.join()
t2.join()
t3.join()
t4.join()
print("Parallel run time: %.2f seconds" % (time.time() - start_time))
python3 t.py
Sequential run time: 2.10 seconds
Parallel run time: 1.41 seconds
Для меня параллельная работа была быстрее.
Ответ 7
На Raspberry Pi 3 Модель B Rev 1.2
[email protected]:~/smart/cpu $ python2 core.py
Sequential run time: 2.34 seconds
Parallel run time: 1.74 seconds
[email protected]:~/smart/cpu $ python2.7 core.py
Sequential run time: 2.34 seconds
Parallel run time: 1.74 seconds
[email protected]:~/smart/cpu $ python3 core.py
Sequential run time: 2.32 seconds
Parallel run time: 1.74 seconds
[email protected]:~/smart/cpu $ python3.4 core.py
Sequential run time: 2.32 seconds
Parallel run time: 1.74 seconds
Ответ 8
Я думаю, что иногда в последовательном режиме было бы лучше, если бы вы нашли ядро с низкой нагрузкой, а не параллельное из сильно загруженных ядер...
Ответ 9
то же самое для меня. параллель была быстрее.
range(10000)
Sequential run time: 228.56 seconds
Parallel run time: 147.03 seconds
Raspberry Pi 3 B+
Raspbian v 4.19.57-v7+ #1244
Python v. 3.5.3
GCC v. 6.3
Во время последовательного процесса загрузка процессора достигает 25%, а во время параллельного процесса загрузка процессора достигает 100%.