2013-10-11 2 views
1

У меня есть две простые функции (петли над диапазоном), которые могут выполняться отдельно без какой-либо зависимости. Я пытаюсь запустить эти 2 функции как с помощью модуля многопроцессорности Python, так и с помощью модуля многопоточности. .Многопроцессорное время на многопоточное время Python

Когда я сравнил вывод, я вижу приложение занимает несколько процессов 1 секунду больше, чем многопоточность модуль в ..

Я прочитал многопоточность не так эффективна из-за глобальным блокировки переводчика ...

Исходя из вышесказанного stmts - 1. Лучше всего использовать множитель обрабатывать, если нет зависимости между двумя процессами? 2. Как рассчитать количество процессов/потоков, которые я могу запустить в моей машине для достижения максимальной эффективности .. 3. Кроме того, есть ли способ, чтобы рассчитать эффективность программы с использованием многопоточности ...

Multithread модуль ...

from multiprocessing import Process 

import thread 
import platform 

import os 
import time 
import threading 
class Thread1(threading.Thread): 
    def __init__(self,threadindicator): 
     threading.Thread.__init__(self) 
     self.threadind = threadindicator 

    def run(self): 
     starttime = time.time() 
     if self.threadind == 'A': 
      process1() 
     else: 
      process2() 
     endtime = time.time() 
     print 'Thread 1 complete : Time Taken = ', endtime - starttime 

def process1(): 
    starttime = time.time() 
    for i in range(100000): 
     for j in range(10000): 
      pass   
    endtime = time.time() 

def process2(): 
    for i in range(1000): 
     for j in range(1000): 
      pass 

def main(): 

    print 'Main Thread' 
    starttime = time.time() 
    thread1 = Thread1('A') 
    thread2 = Thread1('B') 
    thread1.start() 
    thread2.start() 
    threads = [] 
    threads.append(thread1) 
    threads.append(thread2) 

    for t in threads: 
     t.join() 
    endtime = time.time() 
    print 'Main Thread Complete , Total Time Taken = ', endtime - starttime 


if __name__ == '__main__': 
    main() 

модуль нескольких процессов

from multiprocessing import Process 
import platform 

import os 
import time 

def process1(): 
#  print 'process_1 processor =',platform.processor() 
    starttime = time.time() 
    for i in range(100000): 
     for j in range(10000): 
      pass 
    endtime = time.time() 
    print 'Process 1 complete : Time Taken = ', endtime - starttime 


def process2(): 
#  print 'process_2 processor =',platform.processor() 
    starttime = time.time() 
    for i in range(1000): 
     for j in range(1000): 
      pass 
    endtime = time.time() 
    print 'Process 2 complete : Time Taken = ', endtime - starttime 

def main(): 
    print 'Main Process start' 
    starttime = time.time() 
    processlist = [] 

    p1 = Process(target=process1) 
    p1.start() 
    processlist.append(p1) 

    p2 = Process(target = process2) 
    p2.start() 
    processlist.append(p2) 

    for i in processlist: 
     i.join() 
    endtime = time.time() 
    print 'Main Process Complete - Total time taken = ', endtime - starttime 

if __name__ == '__main__': 
    main() 
+0

В качестве примечания стороны: time.time() может иметь точность до 1 секунды, а также может смущаться изменениями часов. Таким образом, это не идеальный способ измерения производительности, особенно для кода, который занимает около секунды. – abarnert

ответ

5

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

Global Interpreter Lock (GIL) не позволяет интерпретатору Python эффективно использовать более одного процессора, используя несколько потоков, поскольку только один поток может выполнять байт-код Python за раз. Поэтому многопоточность не улучшит общее время выполнения вашего приложения, если у вас нет блокировок (например, ожидания ввода-вывода) или освобождения GIL (например, будет делать это для некоторых дорогостоящих вызовов) в течение продолжительных периодов времени. Однако библиотека многопроцессорности создает отдельные подпроцессы и, следовательно, несколько копий интерпретатора, поэтому может эффективно использовать несколько процессоров.

Однако в примере, который вы указали, у вас есть один процесс, который заканчивается очень быстро (менее 0,1 секунды на моей машине) и один процесс, который занимает около 18 секунд, чтобы закончить с другой. Точные цифры могут отличаться в зависимости от вашего оборудования. В этом случае почти вся работа выполняется в одном процессе, поэтому вы действительно используете только один ЦП. В этом случае увеличение накладных расходов на процессы нереста и потоков, вероятно, приводит к замедлению работы на основе процесса.

Если вы делаете оба процесса выполняющими 18-секундные вложенные циклы, вы должны увидеть, что многопроцессорный код идет намного быстрее (при условии, что на вашем компьютере фактически имеется более одного ЦП). На моей машине я видел, что код многопроцессорности заканчивается около 18,5 секунд, а многопоточный код заканчивается через 71,5 секунды. Я не уверен, почему многопоточность заняла больше, чем около 36 секунд, но я предполагаю, что GIL вызывает какую-то проблему конфликтов потоков, которая замедляет выполнение обоих потоков.

Что касается вашего второго вопроса, предполагая, что в системе нет другой нагрузки, вы должны использовать несколько процессов, равных количеству процессоров в вашей системе. Вы можете обнаружить это, выполнив lscpu в системе Linux, sysctl hw.ncpu в системе Mac или запустив dxdiag из диалогового окна «Запуск» в Windows (возможно, есть другие способы, но я всегда это делаю).

Для третьего вопроса самый простой способ выяснить, насколько эффективно вы получаете от дополнительных процессов, просто измерить общую продолжительность работы вашей программы, используя time.time(), как вы были, или утилиту time в Linux (например time python myprog.py). Идеальное ускорение должно быть равно количеству процессов, которые вы используете, поэтому 4-процессорная программа, работающая на 4-х процессорах, должна быть не более 4 раза быстрее, чем одна и та же программа с 1 процессом, если вы получите максимальную выгоду от дополнительных процессов , Если другие процессы вам не помогут, это будет меньше 4x.

+0

«Глобальная блокировка интерпретатора (GIL) не позволяет интерпретатору Python эффективно использовать более одного процессора с использованием нескольких потоков, поскольку за один раз может выполняться только один поток». Это ** false **. Потоки Python ** могут выполняться одновременно. То, что они не могут сделать, это одновременно выполнять * bytecode *. Если один поток выполняет дорогостоящий вызов «numpy», тогда другие потоки python будут выполняться одновременно, так как «numpy» освобождает GIL. Аналогичным образом, расширение C расширяет GIL во время дорогостоящих операций. – Bakuriu

+0

Спасибо за разъяснение - я не думаю, что это было ясно в моем сознании. Я отредактировал свой ответ, чтобы быть более точным в этом вопросе. – airfrog

+0

Вы можете получить количество CPU [изнутри Python] (http://docs.python.org/2/library/multiprocessing.html#misc Miscellaneous), что лучше, чем редактирование кода вручную для каждой машины. – abarnert

Смежные вопросы