调查joblib减速

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了调查joblib减速相关的知识,希望对你有一定的参考价值。

我正在尝试使用joblib并行制作自定义随机森林实施列车。

任务是令人尴尬的平行,所以我假设加速不应该太辛苦与joblib。

这是一些示例代码:

class RandomForest(object):
    def __init__(self, settings, data):
        self.forest = [None] * settings.n_trees
        self.parallel = Parallel(n_jobs=settings.njobs, backend="threading")

    def fit(self, data, train_ids_current_minibatch, settings, param, cache):
        self.forest = self.parallel(
            delayed(_parallel_build_trees_batch)(
                i_t, data, train_ids_current_minibatch, settings, param, cache)
            for i_t, tree in enumerate(self.forest))

    def partial_fit(self, data, train_ids_current_minibatch, settings, param, cache):
        self.forest = self.parallel(
            delayed(_parallel_build_trees_partial)(
                tree, i_t, data, train_ids_current_minibatch, settings, param, cache)
            for i_t, tree in enumerate(self.forest))

但是,在批处理和增量情况下,使用多个作业时,培训速度要慢得多。数据和缓存参数是包含(大)numpy数组的dicts,所以我想知道这是否是原因。

我尝试使用multiprocessing.Pool进行相同的编码,结果更糟,因为没有使用joblib的threading后端,我假设因为fit函数大量使用numpy / scipy代码。

关于如何调试/修复减速的任何想法?

答案

你的分析对我来说似乎是正确的:减速是由datacache作为大型物体引起的。现在,在多处理环境中,您没有共享内存,因此您需要以某种方式共享这些对象。 Python通过shared objects支持这个:有一个“主进程”真正拥有对象。但是其他进程需要通过某种机制发送所有更新(AFAIK对象被pickle然后通过管道或队列发送),这会减慢它的速度。

我看到了一些选项:

  • 转换你的代码,使它使用分区:我不熟悉随机森林。我想每个进程都有data作为初始数据集然后你试图找到一个“最佳”。如果您可以推送进程1以查找所有“类型A”优化,并且进程2找到所有“类型B”优化,然后让每个进程例如将他们的发现写在文件rf_process_x.txt的磁盘上然后你不需要共享内存状态
  • 转换你的代码,使它使用队列(参见this page上的最后一个例子):如果分区不起作用,那么你可以: 启动n个工作进程 每个过程为自己建立他的data集(所以它不在共享内存中) 在主要过程中,您将“作业”放入task_queue,例如使用此特定参数集查找随机森林。 worker从task_queue获取作业,计算它并将其结果放在result_queue上。如果任务和结果很慢,这只是很快,因为这些对象需要被腌制并通过管道从父进程发送到工作进程。
  • 使用joblib memmap ping:qazxsw poi将对象转储到磁盘上,然后为每个对象提供对该文件的内存映射访问
  • 如果您的操作不受CPU限制(执行大量磁盘或网络操作),您可以转向多线程。这样你真的有一个共享内存。但据我所知,你是cpu绑定并将遇到“GIL锁定”问题(在cpython中一次只运行一个线程)
  • 您可以找到加速随机森林的其他方法,例如: Joblibs supports提到了一些

以上是关于调查joblib减速的主要内容,如果未能解决你的问题,请参考以下文章

11.按要求编写Java应用程序。 创建一个叫做机动车的类: 属性:车牌号(String),车速(int),载重量(double) 功能:加速(车速自增)减速(车速自减)修改车牌号,查询车的(代码片段

按要求编写Java应用程序。 创建一个叫做机动车的类: 属性:车牌号(String),车速(int),载重量(double) 功能:加速(车速自增)减速(车速自减)修改车牌号,查询车的载重量(代码片段

Pyinstaller没有编译joblib

为啥在使用 joblib.Parallel 时保护主循环很重要?

Python - 使用 joblib 进行循环并行化

Python多处理(joblib)参数传递的最佳方式