如何使用多核心在sklearn dbscan中?

4

我正在尝试通过dbscan处理大量数据,并希望利用机器上可用的所有核心来加速计算。我正在使用自定义距离度量,但是距离矩阵没有预先计算。

我尝试了许多不同的实现,但并没有取得很大的成功。我在下面列出了它们,并跟踪了终端窗口中的性能表现。

  1. 使用内置的n_jobs输入:
model = DBSCAN(eps=eps, min_samples=min_samps,metric=distance_sphere_and_time, n_jobs=-1)
model.fit(X)

CPU仅使用了2%。看起来只有48个可能的核心中的一个被包含在计算中。

  1. 使用内置的n_jobs输入以及算法Brute
model = DBSCAN(eps=eps, min_samples=min_samps,metric=distance_sphere_and_time, algorithm=`Brute`, n_jobs=-1)
model.fit(X)

在这里建议使用dbscan进行并行处理的唯一方法是:https://github.com/scikit-learn/scikit-learn/pull/8039。尽管有警告,但Brute可能会使它变慢。CPU使用率达到了100%,但速度并没有更快。
3. 使用dask进行并行处理。
client = Client(processes=False, n_workers=8)
    model = DBSCAN(eps=eps, min_samples=min_samps,metric=distance_sphere_and_time)
    with parallel_backend('dask'):
        model.fit(X)

在这里建议采用的实现方式是:https://github.com/dask/dask-tutorial/issues/80。然而,CPU 利用率仍然保持在 2%,表明只使用了一个核心。

非常感谢任何建议。


更新一下 - 我通过在Client中删除输入并在DBSCAN中添加n_jobs=-1来增加了CPU利用率。我无法让它使用所有可用的核心,但确实将CPU使用率提高到了约35%。client = Client() model = DBSCAN(eps=eps, min_samples=min_samps, metric=distance_sphere_and_time, n_jobs=-1) - Lauren K
2个回答

1
你的问题在于 Python。尝试使用其他工具,比如 ELKI (不要忘记添加例如覆盖树索引),你会发现速度巨大的差异。
原因在于你的距离是用户函数。sklearn 用球树来搜索邻居,这需要 Cython,并且对于每个距离计算,它需要返回到解释器。甚至每个距离计算都会复制点数据。这些回调可能涉及臭名昭著的 Python GIL,从而破坏任何并行化努力。

0

-使用Dask并行处理,processes=False告诉dask使用多线程而不是多进程,这对于调用GIL的工作流程不推荐。(参考文档:https://docs.dask.org/en/latest/scheduling.html

因此,您可以使用以下内容以获得更好的性能: client = Client(processes=True, n_workers=number_of_cpu_cores, threads_per_worker=1)

其中n_workers等于您拥有的CPU核心数,threads_per_worker=1告诉dask在每个worker上使用一个进程和一个线程。还要注意,processes=True是默认配置,因此您不需要明确提及。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接