Python多处理Pool.map并不比调用函数一次快

时间:2014-04-29 20:07:28

标签: python

我有一个非常大的字符串列表(最初来自文本文件),我需要使用python进行处理。最终我试图采用map-reduce风格的并行处理。

我编写了一个“mapper”函数并将其提供给multiprocessing.Pool.map(),但它与使用完整数据集调用mapper函数所花费的时间相同。我一定是做错了。

我尝试了多种方法,都有类似的结果。

def initial_map(lines):
    results = []
    for line in lines:
        processed = # process line (O^(1) operation)
        results.append(processed)
    return results

def chunks(l, n):
    for i in xrange(0, len(l), n):
        yield l[i:i+n]

if __name__ == "__main__":
    lines = list(open("../../log.txt", 'r'))
    pool = Pool(processes=8)
    partitions = chunks(lines, len(lines)/8)
    results = pool.map(initial_map, partitions, 1)

因此,chunks函数会生成原始行集的子列表列表以提供给pool.map(),然后它应该将这8个子列表交给8个不同的进程并通过映射器函数运行它们。当我运行它时,我可以看到我的所有8个核心达到峰值100%。然而它需要22-24秒。

当我简单地运行它(单个进程/线程)时:

lines = list(open("../../log.txt", 'r'))
results = initial_map(results)

大约需要相同的时间。 ~24秒。我只看到一个进程达到100%CPU。

我也试过让游戏池自行拆分并让映射器函数一次只处理一行,结果相似。

def initial_map(line):
    processed = # process line (O^(1) operation)
    return processed

if __name__ == "__main__":
    lines = list(open("../../log.txt", 'r'))
    pool = Pool(processes=8)
    pool.map(initial_map, lines)

~22秒。

为什么会这样?并行化这应该会导致更快的结果,不是吗?

1 个答案:

答案 0 :(得分:1)

如果在一次迭代中完成的工作量非常小,那么您只需花费很大一部分时间与子进程进行通信,这是很昂贵的。相反,尝试将更大的数据片段传递给处理函数。如下所示:

slices = (data[i:i+100] for i in range(0, len(data), 100)

def process_slice(data):
    return [initial_data(x) for x in data]

pool.map(process_slice, slices)

# and then itertools.chain the output to flatten it

(没有我的补偿。所以不能给你一个完整的工作解决方案,也不能验证我说的话)

修改或查看@ubomb的问题的第3条评论。