dask.delayed无法加速

时间:2018-08-18 12:18:05

标签: python parallel-processing multiprocessing dask

我正试图进入达斯克。为此,我试图并行化我得到的一些耗时的顺序代码。原始代码是这样的:

def sequential():
    sims = [] 
    chunksize = len(tokens)//4
    for i in range(0, len(tokens), chunksize):
        print(i, i+chunksize)
        chunk = tokens[i:i+chunksize]
        sims.append(process(chunk))     
    return sims

%time sequential()

和通用代码是这样的:

def parallel():
    sims = []
    chunksize = len(tokens)//4
    for i in range(0, len(tokens), chunksize):
        print(i, i+chunksize)
        chunk = dask.delayed(tokens[i:i+chunksize])
        sims.append(dask.delayed(process)(chunk))
    return dask.delayed(sims)

%time parallel().visualize()

但是并行代码始终比并行代码慢10%。当我可视化sims的计算图时,我得到了:

enter image description here

不确定list-#8的来源,但看起来还是正确的。那么为什么没有加速呢?当我查看htop时,我看到3个核心处于活动状态(每个负载约30%),而对于顺序代码,我仅看到1个核心处于活动状态(负载100%)。顺序代码运行7分钟,而并行代码运行7-8分钟。

我想我误会了delayedcompute在这里应该使用吗?


如果需要,设置是这样的:

import numpy
import spacy
import dask

nlp = spacy.load('en_core_web_lg')

tokens = [t for t in nlp(" ".join(t.strip() for t in open('./words.txt','r').readlines())) if len(t.text) > 1 and len(t.text) < 20]


def process(chunk):
    sims = numpy.zeros([len(chunk),len(tokens)], dtype=numpy.float32)
    for i in range(len(chunk)):
        for j in range(len(tokens)):
            sims[i,j] = chunk[i].similarity(tokens[j])
    return sims 

1 个答案:

答案 0 :(得分:2)

您正在看到此行为,因为dask的默认执行引擎基于单个进程中的多个线程(“线程”调度程序)。 Python具有一个锁GIL,该锁通过一次仅执行一个python语句来确保解释器的安全。因此,每个线程都在花费大部分时间等待锁变得可用。 为避免此问题,您有两种选择:

  • 找到发布GIL的计算版本。如果您可以将其表达为(主要是)一些numpy,pandas,numba等计算,在C级别执行并且不需要解释器的代码,则这是可能的,这与嵌套循环不同。
  • 使用进程,使用“ mutiprocessing”调度程序或(更好)“分布式”调度程序来运行您的代码,尽管名称如此,但该调度程序也可以在一台计算机上很好地运行。

更多信息:http://dask.pydata.org/en/latest/scheduler-overview.html