Как работать с интерактивно определенными классами в IPython.parallel?

контекст

В интерактивной разработке прототипов на ноутбуке, подключенном к кластеру, я хотел бы определить класс, который доступен в клиенте __main__ сеанс и интерактивно обновлять узлы механизма кластера, чтобы иметь возможность перемещать экземпляры этого класса, передавая такие экземпляры в качестве аргумента представлению LoadBalanced. Ниже показан типичный сеанс пользователя:

Сначала настройте среду параллельной кластеризации:

>>> from IPython.parallel import Client
>>> rc = Client()
>>> lview = rc.load_balanced_view()
>>> rc[:]
<DirectView [0, 1, 2]>

В ячейке записной книжки давайте определим фрагмент кода компонента, который мы редактируем в интерактивном режиме:

>>> class MyClass(object):
...     def __init__(self, parameter):
...         self.parameter = parameter
...
...     def update_something(self, some_data):
...         # do something smart here with some_data & internal state
...
...     def compute_something(self, other_data):
...         # do something smart here with other data & internal state
...         return something
...

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

>>> def process(obj, some_data, other_data):
...     obj.update_something(some_data)
...     return obj.compute_something(other_data)
...
>>> tasks = []
>>> some_instances = [MyClass(i) for i in range(10)]
>>> for obj in some_instances:
...    for some_data in data_source_1:
...         for other_data in data_source_2:
...             ar = lview.apply_async(process, obj, some_data, other_data)
...             tasks.append(ar)
...
>>> # wait for computation to end
>>> results = [ar.get() for ar in tasks] 

проблема

Это, очевидно, не сработает, так как механизмы представления с балансировкой нагрузки не смогут распаковать экземпляры, переданные в качестве первого аргумента process функция. Само определение функции процесса прошло успешно, так как я предполагаю, что apply_async делает байт-код инстроспекция, чтобы засолить его (путем доступа к .code атрибут функции), а затем просто делает простой рассол для оставшихся аргументов.

Возможные решения (которые не работают для меня)

  • Одним из альтернативных решений будет использование %%px клеточная магия на клетке, содержащей определение класса MyClass, Однако это помешало бы мне создавать экземпляры классов в клиентском скрипте, который также выполняет планирование. Мне нужно будет скопировать и вставить содержимое ячейки в другую ячейку без %%px магия (или выполнить ячейку дважды, один раз с помощью магии, а другой раз без магии), но это утомительно, когда я все еще редактирую методы класса в итеративной настройке разработки и оценки.

  • Альтернативным решением было бы встроить определение класса в process функция, но я нахожу это не практичным, поскольку я хотел бы повторно использовать это определение класса в других функциях позже в своей записной книжке.

  • В качестве альтернативы я мог бы просто прекратить использование класса и работать только с функциями, которые могут быть отправлены в движки, передав затем в качестве первого аргумента apply_async, Однако мне это тоже не нравится, так как я хотел бы создать прототип своего кода объектно-ориентированным способом для последующего извлечения из записной книжки и включения полученного класса в объектно-ориентированную библиотеку. Сеанс ноутбука служит инструментом совместного прототипирования, который используется для обмена идеями между разработчиками с помощью издателя http://nbviewer.ipython.org/.

  • Последней альтернативой будет написать мой класс в модуле python для файла в файловой системе и отправить этот файл в движки PYTHONPATH, используя, например, NFS. Это работает, но мешает мне работать только в среде ноутбука, что не позволяет реализовать цели интерактивного прототипирования в ноутбуке.

Итак, в принципе, есть ли способ определить класс в интерактивном режиме и затем передать его определение движкам?

Должна быть возможность выбрать определение класса, используя inspect.getsource в клиенте, затем отправьте источник на движки и используйте eval встроенный, но, к сожалению, проверка исходного кода не работает для классов, определенных внутри DummyMod встроенный модуль:

TypeError: <IPython.core.interactiveshell.DummyMod object at 0x10c2c4e50> is a built-in class

Есть ли способ проверить байт-код определения класса вместо этого?

Или можно использовать %%px магия, чтобы выполнить содержимое ячейки локально на клиенте и на каждом движке?

2 ответа

Решение

Спасибо за подробный вопрос (и пингующий меня в Твиттере).

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

rc[:]['MyClass'] = MyClass

но выбор интерактивно определенных классов приводит только к ссылке ('\x80\x02c__main__\nMyClass\nq\x01.'), предоставляя ваш DummyMod AttributeError. Вероятно, это можно исправить внутренне в сериализации IPython.

Впрочем, по фактическому рабочему решению.

Добавление локального исполнения к %%px супер просто, просто

def pxlocal(line, cell):
    ip = get_ipython()
    ip.run_cell_magic("px", line, cell)
    ip.run_cell(cell)
get_ipython().register_magic_function(pxlocal, "cell")

И теперь у вас есть %%pxlocal магия, которая бежит %%px в дополнение к запуску ячейки на месте.

Тогда все, что вам нужно сделать, это:

%%pxlocal

class MyClass(object):
    # etc

определить свой класс везде. Я добавлю --local флаг для %%pxтак что этот дополнительный шаг не нужен.

Полный рабочий пример тетради.

Я думаю, что вы могли бы использовать "укроп" для выбора интерактивно определенного класса, и вам не нужно беспокоиться о магии %%pxlocal, использовании DummyMod и имитации пространств имен.

Чтобы выбрать класс в интерактивном режиме, просто выполните "Импорт укропа", а затем создайте свой класс, как вы это делали сначала. Затем вы сможете отправить его по любой вменяемой карте или функции apply_async.

Другие вопросы по тегам