Я решил изучить, как многопоточность сделана в 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()
когда это может?
Для распараллеливания с Python необходимо использовать многопроцессорный фреймворк. К счастью, модуль multiprocessing , поставляемый с Python, делает это довольно легко.
Очень немногие языки могут автоматически распараллеливать выражения. Если вам нужна именно такая функциональность, я предлагаю Haskell (Data Parallel Haskell)
Проблема в функции random () Если вы удалите из кода random. Оба ядра пытаются получить доступ к общему состоянию случайной функции. Ядра работают последовательно и много времени тратят на синхронизацию кешей. Такое поведение известно как ложное совместное использование. Прочтите эту статью False Sharing