2016-07-12 2 views
4

То, что я пытаюсь сделать, - использовать глобальную переменную каждым процессом. Но мой процесс не принимает глобальные значенияPython Многопроцессорное обмен глобальными значениями

import multiprocessing 

count = 0 

def smile_detection(thread_name): 
    global count 

    for x in range(10): 
     count +=1 
     print thread_name,count 

    return count  

x = multiprocessing.Process(target=smile_detection, args=("Thread1",)) 
y = multiprocessing.Process(target=smile_detection, args=("Thread2",)) 
x.start() 
y.start() 

Я получаю выход как

Thread1 1 
Thread1 2 
. 
. 
Thread1 9 
Thread1 10 
Thread2 1 
Thread2 2 
. 
. 
Thread2 9 
Thread2 10 

, что я хочу это

Thread1 1 
Thread1 2 
. 
. 
Thread1 9 
Thread1 10 
Thread2 11 
Thread2 12 
. 
. 
Thread2 19 
Thread2 20 

Что я должен сделать, чтобы достичь этого?

+0

Посмотрите на [Переменные Глобалы и многопроцессорность Python] (http: // stackoverflow.com/questions/11215554/globals-variables-and-python-multiprocessing) и [Обновления глобальной переменной для многопроцессорной обработки Python не возвращаются родителям] (http://stackoverflow.com/questions/11055303/python-multiprocessing-global-variable- обновления-не-вернулся к родителям). Глобальные переменные не разделяются между * процессами *. Это совершенно разные экземпляры python. – mhoff

ответ

1

В отличие от потоковой обработки многопроцессорность немного сложнее обрабатывать разделяемое состояние из-за разветвления (или нереста) нового процесса. Особенно в окнах. Чтобы иметь общий объект, используйте многопроцессорную обработку .Rray или multiprocessing.Value. В случае массива вы можете в каждом процессе разыменовать свой адрес памяти в другой структуре, например, в массиве numpy. В вашем случае, я хотел бы сделать что-то вроде этого:

import multiprocessing, ctypes 

count = multiprocessing.Value(ctypes.c_int, 0) # (type, init value) 

def smile_detection(thread_name, count): 

    for x in range(10): 
     count.value +=1 
     print thread_name,count 

    return count  

x = multiprocessing.Process(target=smile_detection, args=("Thread1", count)) 
y = multiprocessing.Process(target=smile_detection, args=("Thread2", count)) 
x.start() 
y.start() 
+1

Я действительно не получаю, как применить это. – abhishek

+0

Извините, мой плохой. Ред. – alexpeits

0

Для обмена данных между процессами, вам нужно, чтобы позволить mutiprocessing.Manager управлять разделяемыми данными:

count = multiprocessing.Manager().Value('i', 0) # creating shared variable 
lock = multiprocessing.Manager().Lock() # we'll use lock to acquire lock on `count` before count += 1 

def smile_detection(thread_name): 
    global count 

    for x in range(10): 
     lock.acquire() 
     count +=1 
     lock.release() 
     print thread_name,count 

    return count 
1

Попробуйте делать это так:

import multiprocessing 

def smile_detection(thread_name, counter, lock): 
    for x in range(10): 
     with lock: 
      counter.value +=1 
      print thread_name, counter.value 


count = multiprocessing.Value('i', 0) 
lock = multiprocessing.Lock() 
x = multiprocessing.Process(target=smile_detection, args=("Thread1", count, lock)) 
y = multiprocessing.Process(target=smile_detection, args=("Thread2", count, lock)) 
x.start() 
y.start() 
x.join() 
y.join() 

Первая проблема заключается в том, что глобальные переменные не разделяются между процессами. Вам необходимо использовать механизм с некоторым типом блокировки потоковой синхронизации или синхронизации. Мы можем использовать multiprocessing.Value('i', 0) для создания потокового, синхронизированного целочисленного значения. Мы используем наш multiprocessing.Lock(), чтобы гарантировать, что только один поток может обновлять счетчик одновременно.

Если вы действительно хотите использовать глобальную переменную, вы можете использовать multiprocessing.Manager(), которые могут остаться в глобальной переменной:

import multiprocessing 

count = multiprocessing.Manager().Value('i', 0) 
lock = multiprocessing.Manager().Lock() 

def smile_detection(thread_name): 
    global count, lock 

    for x in range(10): 
     with lock: 
      counter.value +=1 
      print thread_name, counter.value 

x = multiprocessing.Process(target=smile_detection, args=("Thread1",)) 
y = multiprocessing.Process(target=smile_detection, args=("Thread2",)) 
x.start() 
y.start() 
x.join() 
y.join() 

Но лично мне нравится первый способ лучше, как Manager() overcomplicates это ,

Вот результат Сейчас:

$ python test.py 
Thread1 1 
Thread1 2 
Thread1 3 
Thread1 4 
Thread1 5 
Thread1 6 
Thread1 7 
Thread1 8 
Thread1 9 
... 
Thread2 15 
Thread2 16 
Thread2 17 
Thread2 18 
Thread2 19 
Thread2 20 
+0

Я думаю, что блокировка повлияет на мое время обработки, так как будет работать только один поток за раз. – abhishek

+0

Использование Менеджера(). Значение() работало для меня. Спасибо. Кроме того, импортируйте ctypes и затем ссылайтесь на тип как cypes. также помог. – Speakeasys

1

Вы можете использовать multiprocessing.Value:

возвращает объект ctypes выделенный из общей памяти. По умолчанию возвращаемое значение является фактически синхронизированной оболочкой для объекта.

код будет выглядеть так:

import multiprocessing 

count = multiprocessing.Value('i', 0) 

def smile_detection(thread_name, count): 
    for x in range(10): 
     count += 1 
     print thread_name, count 

x = multiprocessing.Process(target=smile_detection, args=("Thread1",count)) 
y = multiprocessing.Process(target=smile_detection, args=("Thread2",count)) 

x.start() 
y.start() 
x.join() 
y.join() 

Имейте в виду, что выход будет, вероятно, не будет один, что вы ожидаете. В вашей ожидаемой производительности на самом деле все итерации Thread 1 доходят до Thread 2. Это не относится к многопоточным приложениям. Если вы хотите, чтобы это произошло, ну, вы не хотите, чтобы он был пронизан резьбой!