Блокнот ipython: как распараллелить внешний скрипт

Я пытаюсь использовать параллельные вычисления из параллельной библиотеки ipython. Но у меня мало знаний об этом, и мне трудно читать документ от человека, который ничего не знает о параллельных вычислениях.

Как ни странно, все руководства, которые я нашел, просто повторно используют пример в документе с тем же объяснением, которое, с моей точки зрения, бесполезно.

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

for my_file in $(cat list_file); do
    python pgm.py my_file &
done

Но интерпретатор bash ноутбука Ipython не поддерживает фоновый режим.

Похоже, решение заключалось в использовании параллельной библиотеки от ipython.

Я попытался :

from IPython.parallel import Client
rc = Client()
rc.block = True
dview = rc[:2] # I take only 2 engines

Но тогда я застрял. Я не знаю, как запустить дважды (или более) один и тот же скрипт или pgm одновременно.

Спасибо.


person jrjc    schedule 19.06.2014    source источник


Ответы (2)


Через год мне наконец удалось получить то, что я хотел.

1) Создайте функцию с тем, что вы хотите делать на другом процессоре. Здесь это просто вызов скрипта из bash командой ! magic ipython. Я думаю, это будет работать с функцией call().

def my_func(my_file):
    !python pgm.py {my_file}

Не забывайте {} при использовании !

Также обратите внимание, что путь к my_file должен быть абсолютным, так как кластеры находятся там, где вы начали блокнот (при выполнении jupyter notebook или ipython notebook), а не обязательно там, где находитесь вы.

2) Запустите свой кластер ноутбуков ipython с нужным количеством ЦП. Подождите 2 секунды и выполните следующую ячейку:

from IPython import parallel
rc = parallel.Client()
view = rc.load_balanced_view()

3) Получите список файлов, которые вы хотите обработать:

files = list_of_files

4) Асинхронно сопоставьте вашу функцию со всеми вашими файлами с view ваших только что созданных движков. (не уверен в формулировке).

r = view.map_async(my_func, files)

Пока он работает, вы можете делать что-то еще в блокноте (он работает в «фоновом режиме»!). Вы также можете вызвать r.wait_interactive(), который интерактивно подсчитывает количество обработанных файлов, количество затраченного времени и количество оставшихся файлов. Это помешает вам запускать другие ячейки (но вы можете прервать это).

И если у вас больше файлов, чем движков, не беспокойтесь, они будут обработаны, как только движок завершит работу с 1 файлом.

Надеюсь, это поможет другим!

Этот урок может быть полезен:

http://nbviewer.ipython.org/github/minrk/IPython-parallel-tutorial/blob/master/Index.ipynb

Обратите также внимание, что у меня все еще есть IPython 2.3.1, я не знаю, изменилось ли оно с Jupyter.

Изменить: по-прежнему работает с Jupyter, см. здесь различия и возможные проблемы, с которыми вы можете столкнуться< /а>


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

%px import numpy as np

or

%%px
import numpy as np
import pandas as pd

То же самое с переменными и другими функциями, вам нужно поместить их в пространство имен движка:

rc[:].push(dict(
                foo=foo,
                bar=bar))

person jrjc    schedule 30.07.2015
comment
Спасибо за ответ, эта работа идеальна даже в Jupyter Lab! - person Feishi; 04.11.2018

Если вы пытаетесь выполнять некоторые внешние сценарии параллельно, вам не нужно использовать параллельную функциональность IPython. Репликация параллельного выполнения bash может быть достигнута с помощью модуля подпроцесса следующим образом:

import subprocess

procs = []
for i in range(10):
    procs.append(subprocess.Popen(['ls', '/Users/shad/tmp/'], stdout=subprocess.PIPE))

results = []
for proc in procs:
    stdout, _ = proc.communicate()
    results.append(stdout)

Имейте в виду, что если ваш подпроцесс генерирует много вывода, процесс будет заблокирован. Если вы распечатаете вывод (результаты), вы получите:

print results

['file1\nfile2\n', 'file1\nfile2\n', 'file1\nfile2\n', 'file1\nfile2\n', 'file1\nfile2\n', 'file1\nfile2\n', 'file1\nfile2\n', 'file1\nfile2\n', 'file1\nfile2\n', 'file1\nfile2\n']
person shadanan    schedule 19.06.2014
comment
Спасибо за ответ. Не могли бы вы объяснить разницу с вызовом os.popen("""the_bash_script_above""") ? И/или объяснить часть communicate? - person jrjc; 20.06.2014
comment
os.popen устарел, начиная с Python 2.6. Метод Communication() возвращает стандартный вывод и стандартную ошибку для процессов, в которых вы запросили стандартный вывод или стандартный вывод в качестве PIPE. См. документацию для модуля подпроцесса здесь: docs.python.org /2/библиотека/ - person shadanan; 21.06.2014