2016-12-22 10 views
0

Я экспериментировал с моим кодом для отправки «параллельных» команд на несколько последовательных COM-портов.Python Multiprocessing немного медленнее, чем многопоточность в Windows

Мой многопоточность Код состоит из:

global q 
q = Queue() 
devices = [0, 1, 2, 3] 
for i in devices: 
    q.put(i) 
cpus=cpu_count() #detect number of cores 
logging.debug("Creating %d threads" % cpus) 
for i in range(cpus): 
    t = Thread(name= 'DeviceThread_'+str(i), target=testFunc1) 
    t.daemon = True 
    t.start() 

и код многопроцессорной обработки состоит из:

devices = [0, 1, 2, 3] 
cpus=cpu_count() #detect number of cores 
pool = Pool(cpus) 
results = pool.map(multi_run_wrapper, devices) 

Я наблюдаю, что задача отправки последовательных команд 4 COM портов «параллельно «занимает около 6 секунд, а многократная обработка всегда занимает от 0,5 до 1 секунды дополнительного времени работы.

Любые данные о причинах несоответствия на машине Windows?

+1

У многопроцессорной обработки всегда есть дополнительные накладные расходы и многопоточность. Многопоточность использует то же пространство памяти, что и родительский процесс, тогда как для многопроцессорной обработки требуется выделить новую память для процесса. Там, вероятно, больше факторов, чем в игре, но эти накладные расходы являются заданными. –

ответ

1

Ну, например, вы не сравниваете яблоки с яблоками. Если вам нужен эквивалентный код, используйте multiprocessing.dummy.Pool в своем поточном корпусе (что то же самое, что и multiprocessing.Pool, реализованное в терминах потоков, а не процессов), поэтому вы, по крайней мере, используете одну и ту же базовую модель параллелизации с разными внутренними реализациями, не меняя все однажды.

Помимо этого, запуск рабочих и передача данных для них имеет некоторые накладные расходы, больше на Windows, чем на других системах, поскольку Windows не может fork не создавать новые процессы дешево; он должен создать новый экземпляр Python, а затем скопировать его через IPC, чтобы приблизиться к форсированию.

Кроме того, вы не предоставили достаточную информацию; ваши рабочие и потоковые рабочие функции не предоставляются и могут вызывать существенные различия в поведении. Вы также не указали информацию о том, как вы выполняете синхронизацию. Аналогично, если каждый рабочий процесс должен повторно инициализировать библиотеку связи COM-порта, это может включать в себя нетривиальные служебные данные.

+0

Спасибо за ваши данные. Рабочие функции одинаковы для обоих методов (многопоточность и многопроцессорность), за исключением вызовов q.put()/q/taskdone() в многопоточном режиме. И в каждом экземпляре потока я инициализирую новый COM-порт, поэтому на самом деле это не накладные расходы, поскольку я не пытаюсь повторно инициализировать один и тот же COM-порт. На данный момент я думаю, что я буду продолжать многопоточность, поскольку она кажется довольно стабильной для того, что я пытаюсь сделать, и сравнительно быстрее. (используя разницу времени начала-остановки, используя библиотеку времени, чтобы время это). – eecs