Функция multiprocessing.Pool.map не видит переменные в глобальном пространстве имен - PullRequest
0 голосов
/ 12 февраля 2020

Этот игрушечный скрипт завершается ошибкой:

import numpy as np
import multiprocessing as mp

def myFunc1(x):
    return x+c

if __name__ == '__main__':
    c = np.array([[1,1],[1,1]])
    b = np.array([[[1,2],[3,4]],[[5,6],[7,8]]])
    pool = mp.Pool(processes=1)
    result = pool.map(myFunc1,b)
    for i in range(len(result)):
        print(result[i])

с ошибкой

RemoteTraceback: 
"""
Traceback (most recent call last):
  File "C:\Users\aldo.dottavio\anaconda3\lib\multiprocessing\pool.py", line 119, in worker
    result = (True, func(*args, **kwds))
  File "C:\Users\aldo.dottavio\anaconda3\lib\multiprocessing\pool.py", line 44, in mapstar
    return list(map(*args))
  File "C:\Users\aldo.dottavio\Projects\THEIAA\2020-02 parallel processing\untitled0.py", line 12, in myFunc1
    return x+c
NameError: name 'c' is not defined
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):

  File "C:\Users\aldo.dottavio\Projects\THEIAA\2020-02 parallel processing\untitled0.py", line 19, in <module>
    result = pool.map(myFunc1,b)

  File "C:\Users\aldo.dottavio\anaconda3\lib\multiprocessing\pool.py", line 266, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()

  File "C:\Users\aldo.dottavio\anaconda3\lib\multiprocessing\pool.py", line 644, in get
    raise self._value

NameError: name 'c' is not defined

Я ожидал получить

[[2,3]
 [4,5]]
[[6,7]
 [8,9]]

в результате, но вместо c не определено в myFunc1 . Я думаю, что это вызвано map и что при использовании map для применения myFunc1 к данным myFunc1 теряет доступ к глобальное пространство имен.

Подобный игрушечный скрипт завершается успешно:

import numpy as np

def myFunc1(x):
    return x+c

if __name__ == '__main__':
    c = np.array([[1,1],[1,1]])
    b = np.array([[[1,2],[3,4]],[[5,6],[7,8]]])
    result = myFunc1(b)
    for i in range(len(result)):
        print(result[i])

и выводит результат

[[2 3]
 [4 5]]
[[6 7]
 [8 9]]

, как и ожидалось.

Вышеприведенное просто для иллюстрации проблема; в реальном скрипте функция более сложна и должна повторяться по тысячам матриц.

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

Как получить доступ к глобальным переменным из функции в map ? Я не хочу делать копии параметров - параметры составляют всего ~ 1 МБ данных, но в итерируемом элементе может быть около 15 000 элементов.

1 Ответ

0 голосов
/ 13 февраля 2020

Я решил это, используя starmap и itertools.product ()

import numpy as np
import multiprocessing as mp
from itertools import product

def myFunc1(x,c):
    return x+c

if __name__ == '__main__':

    c = np.array([[1,1],[1,1]])
    b = np.array([[[1,2],[3,4]],[[5,6],[7,8]]])
    pool = mp.Pool(processes=1)
    result = pool.starmap(myFunc1,product(b,[c]))
    # result = myFunc1(b)
    for i in range(len(result)):
        print(result[i])

Используя itertools.product и [] вокруг c позволяет передавать весь массив c как итерацию, состоящую из одного элемента, вместо итерации по первому индексу массива NumPy.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...