Изменение глобальной переменной в многопроцессорности Python [дубликат]

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

46
задан Benjamin 12 December 2013 в 15:06
поделиться

3 ответа

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

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

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

from multiprocessing import Pool, Value
from time import sleep

counter = None

def init(args):
    ''' store the counter for later use '''
    global counter
    counter = args

def analyze_data(args):
    ''' increment the global counter, do something with the input '''
    global counter
    # += operation is not atomic, so we need to get a lock:
    with counter.get_lock():
        counter.value += 1
    print counter.value
    return args * 10

if __name__ == '__main__':
    #inputs = os.listdir(some_directory)

    #
    # initialize a cross-process counter and the input lists
    #
    counter = Value('i', 0)
    inputs = [1, 2, 3, 4]

    #
    # create the pool of workers, ensuring each one receives the counter 
    # as it starts. 
    #
    p = Pool(initializer = init, initargs = (counter, ))
    i = p.map_async(analyze_data, inputs, chunksize = 1)
    i.wait()
    print i.get()
50
ответ дан RaveTheTadpole 19 August 2018 в 12:48
поделиться
  • 1
    @jkp, как бы вы сделали это без глобальной переменной? - Я пытаюсь использовать класс, но это не так просто, как кажется. См. stackoverflow.com/questions/1816958/… – Anna 16 December 2011 в 16:05
  • 2
    К сожалению, этот пример кажется ошибочным, так как counter.value += 1 не является атомарным между процессами, поэтому значение будет неправильным, если запустить достаточно долго с несколькими процессами – Eli Bendersky 31 December 2011 в 12:25
  • 3
    В соответствии с тем, что сказал Эли, Lock должен окружать инструкцию counter value += 1. См. stackoverflow.com/questions/1233222/… – A-B-B 17 July 2012 в 20:32
  • 4
    Обратите внимание, что это должно быть with counter.get_lock(), а не with counter.value.get_lock(): – Jinghao Shi 14 January 2016 в 19:23
  • 5
    @jkp, как сказал @ Jinghao-shi, counter.value.get_lock() будет производить AttributeError: 'int' object has no attribute 'get_lock' – Samuel 30 March 2016 в 07:41

Класс Faster Counter без использования встроенного замка значения дважды

class Counter(object):
    def __init__(self, initval=0):
        self.val = multiprocessing.RawValue('i', initval)
        self.lock = multiprocessing.Lock()

    def increment(self):
        with self.lock:
            self.val.value += 1

    @property
    def value(self):
        return self.val.value

https://eli.thegreenplace.net/2012/01/04/shared-counter-with -pythons-multiprocessing https://docs.python.org/2/library/multiprocessing.html#multiprocessing.sharedctypes.Value https://docs.python.org /2/library/multiprocessing.html#multiprocessing.sharedctypes.RawValue

1
ответ дан RiTu 19 August 2018 в 12:48
поделиться

Класс Counter без ошибки состояния гонки:

class Counter(object):
    def __init__(self):
        self.val = multiprocessing.Value('i', 0)

    def increment(self, n=1):
        with self.val.get_lock():
            self.val.value += n

    @property
    def value(self):
        return self.val.value
26
ответ дан serbaut 19 August 2018 в 12:48
поделиться
Другие вопросы по тегам:

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