多处理比python中的线程慢

时间:2018-12-11 09:56:20

标签: python multithreading multiprocessing

我已经在python中测试了多进程和线程,但是多进程比线程慢,并且我使用editdistance计算距离,我的代码如下:

def calc_dist(kw, trie_word):
    dists = []

    while len(trie_word) != 0:
        w = trie_word.pop()
        dist = editdistance.eval(kw, w)
        dists.append((w, dist))

    return dists

if __name__ == "__main__":
    word_list = [str(i) for i in range(1, 10000001)]
    key_word = '2'
    print("calc")
    s = time.time()
    with Pool(processes=4) as pool: 
        result = pool.apply_async(calc_dist, (key_word, word_list)) 
        print(len(result.get())) 
    print("用时",time.time()-s)

使用线程:

class DistThread(threading.Thread):
    def __init__(self, func, args):
        super(DistThread, self).__init__()
        self.func = func
        self.args = args
        self.dists = None

    def run(self):
        self.dists = self.func(*self.args)

    def join(self):
        super().join(self)
        return self.dists

在我的计算机上,它消耗约118s,但是线程花费约36s,这是哪里出了问题?

2 个答案:

答案 0 :(得分:3)

几个问题:

  1. 将花费大量时间对数据进行序列化,以便在线程共享相同的地址空间以便可以使用指针的同时将其发送到另一个进程

  2. 您当前的代码仅使用一个进程即可进行多处理的所有计算。您需要以某种方式将数组分隔为“块”,以便可以通过多个工作程序对其进行处理

例如:

import time
from multiprocessing import Pool
import editdistance

def calc_one(trie_word):
    return editdistance.eval(key_word, trie_word)

if __name__ == "__main__":
    word_list = [str(i) for i in range(1, 10000001)]
    key_word = '2'

    print("calc")
    s = time.time()
    with Pool(processes=4) as pool: 
        result = pool.map(calc_one, word_list, chunksize=10000) 
        print(len(result))
    print("time",time.time()-s)

    s = time.time()
    result = list(calc_one(w) for w in word_list)
    print(len(result))
    print("time",time.time()-s)

这取决于key_word是全局变量。对我来说,使用多个进程的版本大约需要5.3秒,而第二个版本大约需要16.9秒。仍然不是来回发送数据的四倍,但是还不错

答案 1 :(得分:0)

我在Python内使用线程和多处理来消耗具有大量数据的CSVS方面也有类似的经验。我对此进行了细小的研究,发现处理产生了多个进程来执行任务,这比仅运行一个线程的进程要慢,因为线程在一个地方运行。这里有一个更明确的答案:Multiprocessing vs Threading Python

从链接中粘贴答案,以防链接消失;

线程模块使用threads,多处理模块使用processes。不同之处在于线程在相同的内存空间中运行,而进程具有单独的内存。这使得在具有多处理的进程之间共享对象更加困难。由于线程使用相同的内存,因此必须采取预防措施,否则两个线程将同时写入同一内​​存。这就是全局解释器锁的作用。

生成进程比生成线程要慢一些。它们一旦运行,就不会有太大的区别。