在 HPC 上使用 scikit-learn 函数的并行选项的简单方法

Posted

技术标签:

【中文标题】在 HPC 上使用 scikit-learn 函数的并行选项的简单方法【英文标题】:Easy way to use parallel options of scikit-learn functions on HPC 【发布时间】:2016-11-30 18:14:00 【问题描述】:

在 scikit-learn 的许多函数中实现了用户友好的并行化。例如在 sklearn.cross_validation.cross_val_score 您只需在 n_jobs 参数中传递所需数量的计算作业。对于具有多核处理器的 PC,它会非常好用。但是如果我想在高性能集群中使用这样的选项(安装了 OpenMPI 包并使用 SLURM 进行资源管理)?据我所知sklearn 使用joblib 进行并行化,它使用multiprocessing。而且,据我所知(据此,例如Python multiprocessing within mpi)Python 程序与multiprocessing 并行化很容易使用mpirun 实用程序扩展整个MPI 架构。我可以仅使用 mpirunn_jobs 参数在多个计算节点上传播 sklearn 函数的计算吗?

【问题讨论】:

你可能想用分布式调度器检查 dask-sklearn,它可以在集群中运行:jcrist.github.io/dask-sklearn-part-1.html @dukebody 你能发布一个使用分布式调度程序的例子吗?我见过的分布式 dask 示例涉及在每台机器上手动创建工作人员并将它们分配给调度程序。我不确定我是否看到这与 dask-sklearn 函数有什么关系。我是否可以像这里一样创建调度程序和工作人员:dask.pydata.org/en/doc-test-build/distributed.html 然后像在您的链接中那样设置默认调度程序(其中 10.0.0.3:8786 是我在第一个链接中创建的调度程序的地址)? 是的。设置过程与您描述的完全一样。见distributed.readthedocs.io/en/latest/setup.html @MRocklin 这似乎对我不起作用。尽管已成功创建工人,但似乎没有对工人执行任何操作。您能否阅读下面的答案和我的 cmets,看看您有什么想法吗? 【参考方案1】:

SKLearn 使用Joblib 管理其并行性。 Joblib 可以将多处理后端换成其他分布式系统,例如 dask.distributed 或 IPython Parallel。详情请参阅sklearn github 页面上的this issue。

将 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://dask.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 参数似乎不再重要了。

使用 SLURM 设置 dask.distributed

对于 SLURM,最简单的方法可能是使用 dask-jobqueue 项目

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

您也可以使用dask-mpi 或Dask's setup documentation 中提到的其他几种方法中的任何一种

直接使用dask.distributed

或者,您可以设置一个 dask.distributed 或 IPyParallel 集群,然后直接使用这些接口来并行化您的 SKLearn 代码。以下是 SKLearn 和 Joblib 开发人员 Olivier Grisel 的示例视频,他们在 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

【讨论】:

我正在尝试让第一个示例正常工作,这里也描述了这个示例:distributed.readthedocs.io/en/latest/joblib.html。我使用dask-ssh 来设置我的调度程序和工作人员。这很好用,如果我打印调度程序对象,我会得到正确数量的内核 (240)。接下来,我在with 语句中包装了对随机搜索的fit 的调用。如果我查看执行dask-ssh 的控制台窗口,我会看到来自运行python 脚本的节点的连接。但是,没有进行分布式工作。它无法扩展,甚至看不到工作人员拥有的 GPU。 我还尝试修改 RandomizedSearchCV 的 n_jobs 参数,设置为 -1110024020 以上的每个值都会导致大致相同的性能,这让我认为分布式工作程序上实际上没有运行任何东西,但是在我运行 python 脚本的节点上(gensim 还会打印一条消息,即没有 GPU。那里是工作节点上的 GPU,但在我运行脚本的节点上没有 GPU)。 在这一点上,你已经超出了我的专业范围。您可以向 joblib 维护者提出问题。我给一个人发了电子邮件并提醒他这个问题,但他们很忙。我还附加了指向实验性 dask-learn 包的答案 好的,谢谢。我尝试了 dklearn,但不幸的是它只是卡住了我,似乎永远不会完成。会坚持下去的。 更新:也试过ipyparallel,我用dask描述的一样。工作人员(ipyparallel 中的引擎)已成功创建,客户端可以看到它们,但我的网格搜索没有在它们上运行。

以上是关于在 HPC 上使用 scikit-learn 函数的并行选项的简单方法的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用 UDF .xll 在 HPC 网格上并行化 Excel

hpc 集群上的 libsnd 文件

R在HPC MPIcluster上运行foreach dopar循环

在PyODPS DataFrame自定义函数中使用pandasscipy和scikit-learn

软标签上的 scikit-learn 分类

在HPC群集上从八度调用R脚本时出错