python中的Threadpool没有预期的那么快

时间:2016-11-25 18:41:39

标签: python multithreading machine-learning feature-extraction

我是python和机器学习的初学者。我尝试使用多线程重现countvectorizer()的代码。我正在使用yelp数据集来使用LogisticRegression进行情绪分析。这是我到目前为止所写的:

代码段:

from multiprocessing.dummy import Pool as ThreadPool
from threading import Thread, current_thread
from functools import partial
data = df['text']
rev = df['stars'] 


y = []
def product_helper(args):
    return featureExtraction(*args)


def featureExtraction(p,t):     
    temp = [0] * len(bag_of_words)
    for word in p.split():
        if word in bag_of_words:
            temp[bag_of_words.index(word)] += 1

    return temp


# function to be mapped over
def calculateParallel(threads): 
    pool = ThreadPool(threads)
    job_args = [(item_a, rev[i]) for i, item_a in enumerate(data)]
    l = pool.map(product_helper,job_args)
    pool.close()
    pool.join()
    return l

temp_X = calculateParallel(12)

这只是代码的一部分。

说明:

df['text']包含所有评论,df['stars']具有评分(1到5)。我试图使用多线程找到单词计数向量temp_Xbag_of_words是一些常用词的列表。

问题:

如果没有多线程,我可以在大约24分钟内计算temp_X,上面的代码需要33分钟才能获得100k评论的数据集。我的机器有128GB的DRAM和12个内核(6个具有超线程的物理内核,即每个内核的线程数= 2)。

我在这里做错了什么?

2 个答案:

答案 0 :(得分:3)

您的整个代码似乎是CPU Bound而不是IO Bound。您只是使用threads下的GIL,因此只运行一个线程加上开销。它只运行于一个核心。要在多个核心上运行,请使用

使用

import multiprocessing
pool = multiprocessing.Pool()
l = pool.map_async(product_helper,job_args)

来自multiprocessing.dummy导入池作为ThreadPool只是thread模块的包装器。它仅使用one core而不是更多。

答案 1 :(得分:1)

Python和线程并不能很好地协同工作。有一个称为GIL(全局间隔器锁)的已知问题。基本上,interperter中有一个锁,它使所有线程不能并行运行(即使你有多个cpu内核)。 Python将简单地为每个线程一个接一个地给出几毫秒的cpu时间(并且它变慢的原因是这些线程之间的上下文切换的开销)。

这是一篇非常好的文档,解释了它的工作原理:http://www.dabeaz.com/python/UnderstandingGIL.pdf

要解决您的问题,我建议您尝试多处理: https://pymotw.com/2/multiprocessing/basics.html

注意:多处理与多线程不是100%相等。多处理将并行运行,但不同的进程不会共享内存,因此如果您更改其中一个变量,则不会在另一个进程中更改。