Я использую модуль Python multiprocessing
для параллельной обработки больших числовых массивов. Массивы отображаются в память с помощью numpy.load(mmap_mode='r')
в главном процессе. После этого multiprocessing.Pool()
разветвляется (я полагаю).
Кажется, все работает нормально, за исключением того, что я получаю строки вроде:
AttributeError("'NoneType' object has no attribute 'tell'",)
in `<bound method memmap.__del__ of
memmap([ 0.57735026, 0.57735026, 0.57735026, 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], dtype=float32)>`
ignored
в логах юниттеста. Тем не менее, испытания проходят нормально.
Есть идеи, что там происходит?
Использование Python 2.7.2, OS X, NumPy 1.6.1.
UPDATE:
После некоторой отладки я выследил причину до пути к коду, который использовал (небольшой кусочек) этот отображаемый в памяти массив numpy в качестве входных данных для вызова Pool.imap
.
Очевидно, «проблема» в том, как multiprocessing.Pool.imap
передает свой вклад новым процессам: он использует pickle. Это не работает с mmap
ed numpy массивами, и что-то внутри разрывается, что приводит к ошибке.
Я нашел этот ответ Роберта Керна, который, похоже, решает ту же проблему. Он предлагает создать специальный путь кода для случая, когда вход imap
поступает из массива с отображением в память: отображение памяти в том же массиве вручную в порожденном процессе.
Это было бы настолько сложно и безобразно, что я бы предпочел жить с ошибкой и дополнительными копиями памяти. Есть ли другой способ облегчить изменение существующего кода?