Python, распараллеливающий неожиданно медленнее

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

Тест, который я изобрел, должен был генерировать большой список случайных чисел и затем распечатать максимум

from random import random
import threading

def ox():
    print max([random() for x in xrange(20000000)])

ox() занимает приблизительно 6 секунд для завершения на моем Intel Core 2 Duo, в то время как ox();ox() занимает приблизительно 12 секунд.

Я затем пытался назвать вола () от двух потоков, чтобы видеть, как быстро, который завершится.

def go():
    r = threading.Thread(target=ox)
    r.start()
    ox()

go() занимает приблизительно 18 секунд для завершения, с двумя печатью результатов в течение 1 секунды друг после друга. Почему это должно быть медленнее?

Я подозреваю ox() параллелизируется автоматически, потому что я если взгляд на вкладку производительности диспетчера задач Windows и вызов ox() в моей консоли Python оба процессора переходят приблизительно к 75%-му использованию, пока это не завершается. Делает Python, автоматически параллелизируют вещи как max() когда это может?

5
задан Martijn Pieters 8 November 2013 в 16:44
поделиться

2 ответа

  1. У Python есть GIL. Байт-код Python будет выполняться только одним процессором за раз. Только определенные модули C (которые не управляют состоянием Python) смогут работать одновременно.
  2. Python GIL имеет огромные накладные расходы на блокировку состояния между потоками. Для этого есть исправления в новых версиях или в ветвях разработки, которые, по крайней мере, должны сделать многопоточный код, привязанный к ЦП, таким же быстрым, как однопоточный код.

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

Очень немногие языки могут автоматически распараллеливать выражения. Если вам нужна именно такая функциональность, я предлагаю Haskell (Data Parallel Haskell)

9
ответ дан 13 December 2019 в 22:01
поделиться

Проблема в функции random () Если вы удалите из кода random. Оба ядра пытаются получить доступ к общему состоянию случайной функции. Ядра работают последовательно и много времени тратят на синхронизацию кешей. Такое поведение известно как ложное совместное использование. Прочтите эту статью False Sharing

1
ответ дан 13 December 2019 в 22:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: