多进程池与asyncio.run_in_executor

时间:2017-08-10 16:21:21

标签: python multithreading scikit-learn multiprocessing

概述

我正在尝试并行化文本分类项目,这个项目肯定需要很长时间才能完全串联运行。我尝试了两种可能的变体,我相信它的功能相似,并且对我在资源监视器中看到的每种结果感到好奇。

第一个解决方案

我尝试的第一件事就是将Python asynciorun_in_executor()一起使用。这是我以前用来并行化一些简单工作的方法,所以我想我试一试。它看起来像这样:

cores = cpu_count()
qty = len(data)
last = 0

coros = []
loop = asyncio.get_event_loop()
for i in range(cores):
    top = ceil((qty * (i + 1)) / cores)
    cor = loop.run_in_executor(None, vect.transform, data[last: top])
    last = int(top)

vectors = loop.run_until_complete(asyncio.gather(*coros))
loop.close()

我的理解是这段代码创建了一个默认的 threads 池,在每个数据块上运行func,并按照它们进入的顺序返回结果。我期待这个最重要的是我的cpu,但它似乎只有15%的运行。从各个处理器来看,只有一半处理器处于使用状态,每个处理器只占20%-30%左右。这种情况一直持续到我不耐烦并停止程序或尝试改变某些东西来简化它。

第二种解决方案

我使用的第二种方法是使用multiprocessing模块及其Pool().map()。这对我来说是新的,但它似乎与第一个解决方案的功能类似,但使用进程,所以我认为它可能以更接近我期望的方式利用处理器。该解决方案如下所示:

cores = cpu_count()
qty = len(data)
last = 0

chunks = []

for i in range(cores):
    top = ceil((qty * (i + 1)) / cores)

    chunks.append(data[last: top])
    last = int(top)

with Pool(processes=cores) as pool:
    vectors = pool.map(vect.transform, chunks)

我相信这段代码应该将数据分块,然后打开新的进程来处理数据。最初,资源监视器完全按照我的预期执行。 CPU使用率达到100%,所有核心都显示为完全活动状态。大约15年后,大部分核心停放,其中两三个核心停留在15%左右。几分钟之后,每个核心似乎都填满了口袋,在任何特定时间平均约为45%,最终完成。

我的期望/问题

稍后在程序中,我将数据拟合到具有n_jobs=-1的sklearn分类器。当发生这种情况时,所有核心都会达到100%。这就是我想做的。所以我有几个问题:

  1. sklearn做什么我不是?
  2. 我的方法中是否有一些我忽视的东西让我的期望变得不切实际?

1 个答案:

答案 0 :(得分:3)

再运行几次后,第二种方法开始按预期运行。我不确定是什么让它发生了变化,但它现在以100%的速度运行CPU。

此外,在做了一些挖掘之后,我得出结论:sklearn可能使用joblib来并行化作业。查看joblib,我发现默认 parallelizing coden_jobs=-1几乎与我的第二个解决方案相同。但总的来说,joblib更加灵活,可以更清晰地编写,以用于更复杂的用例。

相关问题