Я пытаюсь использовать параллельную среду IPython, и пока она выглядит великолепно, но у меня возникла проблема. Допустим, у меня есть функция, определенная в библиотеке
def func(a,b):
...
который я использую, когда хочу оценить одно значение a и несколько значений b.
[func(myA, b) for b in myLongList]
Очевидно, что реальная функция сложнее, но суть в том, что она принимает несколько параметров, и я бы хотел отобразить только один из них. Проблема в том, что карта, @dview.parallel и т. д. отображают все аргументы.
Допустим, я хочу получить ответ на func (myA, myLongList ). Очевидный способ сделать это — каррировать либо с помощью functools.partial, либо просто как
dview.map_sync(lambda b: func(myA, b), myLongList)
Однако это не работает корректно на удаленных машинах. Причина в том, что при мариновании лямбда-выражения значение myA не включается, а вместо этого используется значение myA из локальной области видимости на удаленной машине. Когда замыкания подвергаются консервации, переменные, над которыми они закрываются, не закрываются.
Я могу придумать два способа сделать это, которые действительно будут работать, — это вручную создавать списки для каждого аргумента и выполнять работу с картами для всех аргументов,
dview.map_sync(func, [myA]*len(myLongList), myLongList)
или ужасно использовать данные в качестве аргументов по умолчанию для функции, вынуждая ее мариноваться:
# Can't use a lambda here b/c lambdas don't use default arguments :(
def parallelFunc(b, myA = myA):
return func(myA, b)
dview.map_sync(parallelFunc, myLongList)
Действительно, все это кажется ужасно искаженным, когда реальная функция принимает много параметров и является более сложной. Есть ли какой-то идиоматический способ сделать это? Что-то вроде
@parallel(mapOver='b')
def bigLongFn(a, b):
...
но, насколько я знаю, ничего похожего на 'mapOver' не существует. У меня, вероятно, есть идея, как это реализовать... это похоже на очень простую операцию, для которой должна существовать поддержка, поэтому я хочу проверить, не упустил ли я что-то.