Простой способ использования параллельных функций scikit-learn на HPC

Во многих функциях из scikit-learn реализована удобная распараллеливание. Например, в sklearn.cross_validation.cross_val_score вы просто передаете нужное количество вычислительных заданий в аргументе n_jobs. А для ПК с многоядерным процессором он будет работать очень хорошо. Но если я хочу использовать такой вариант в высокопроизводительном кластере (с установленным пакетом OpenMPI и с использованием SLURM для управления ресурсами)? Как я знаю, sklearn использует joblib для распараллеливания, который использует multiprocessing. И, как я знаю (из этого, например, многопроцессорность Python в mpi) Программы Python, распараллеленные с помощью multiprocessing легко масштабируются oh вся архитектура MPI с помощью утилиты mpirun, Могу ли я распространять вычисления функций sklearn на нескольких вычислительных узлах, используя аргументы mpirun и n_jobs?

Ответы

Ответ 1

SKLearn управляет своим параллелизмом с Joblib. Joblib может заменять многопроцессорную подсистему для других распределенных систем, таких как dask.distributed или IPython Parallel. Смотрите эту проблему на странице sklearn для деталей.

Пример использования Joblib с Dask.distributed

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

from sklearn.externals.joblib import parallel_backend

search = RandomizedSearchCV(model, param_space, cv=10, n_iter=1000, verbose=1)

with parallel_backend('dask', scheduler_host='your_scheduler_host:your_port'):
        search.fit(digits.data, digits.target)

Для этого необходимо настроить планировщик dask.distributed и рабочих в вашем кластере. Общие инструкции доступны здесь: http://distributed.readthedocs.io/en/latest/setup.html

Пример использования Joblib с ipyparallel

Код взят с той же страницы с вопросом.

from sklearn.externals.joblib import Parallel, parallel_backend, register_parallel_backend

from ipyparallel import Client
from ipyparallel.joblib import IPythonParallelBackend

digits = load_digits()

c = Client(profile='myprofile')
print(c.ids)
bview = c.load_balanced_view()

# this is taken from the ipyparallel source code
register_parallel_backend('ipyparallel', lambda : IPythonParallelBackend(view=bview))

...

with parallel_backend('ipyparallel'):
        search.fit(digits.data, digits.target)

Примечание: в обоих приведенных выше примерах параметр n_jobs больше не имеет значения.

Настройте dask.distributed с SLURM

Для SLURM самый простой способ сделать это, вероятно, использовать проект dask-jobqueue

>>> from dask_jobqueue import SLURMCluster
>>> cluster = SLURMCluster(project='...', queue='...', ...)
>>> cluster.scale(20)

Вы также можете использовать dask-mpi или любой из нескольких других методов, упомянутых в документации по настройке Dask.

Используйте dask.distributed напрямую

В качестве альтернативы вы можете настроить кластер dask.distributed или IPyParallel, а затем напрямую использовать эти интерфейсы для распараллеливания вашего кода SKLearn. Вот пример видео SKLearn и разработчика Joblib Оливье Гризеля, делающего именно это в PyData Berlin: https://youtu.be/Ll6qWDbRTD0?t=1561

Попробуйте Dask-ML

Вы также можете попробовать пакет Dask-ML, в котором есть объект RandomizedSearchCV, API-совместимый с scikit-learn, но реализованный в вычислительном отношении поверх Dask.

https://github.com/dask/dask-ml

pip install dask-ml