python 中的线程池没有预期的那么快

Threadpool in python is not as fast as expected

我是 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,而上面的代码对于大小为 100k 的评论的数据集花费了 33 分钟。我的机器有 128GB 的​​ DRAM 和 12 个内核(6 个具有超线程的物理内核,即每个内核的线程数 = 2)。

我做错了什么?

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

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

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

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

您的整个代码似乎是 CPU Bound 而不是 IO Bound。您只是在使用 GIL 下的 threads 如此有效 运行 仅一个线程plus overheads.It 运行s only on one core.To 运行 on multiple cores use

使用

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

from multiprocessing.dummy import Pool as ThreadPool 只是 thread 的包装器 module.It 仅使用 one core 而不是更多。