首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我的Python多线程代码受全局解释器锁的影响吗?

我的Python多线程代码受全局解释器锁的影响吗?
EN

Stack Overflow用户
提问于 2016-09-27 15:43:34
回答 2查看 1.2K关注 0票数 2

我正在尝试使用ThreadPool来加速我的代码。

输入是一个包含大约80000个元素的字典,每个元素都是一个由25个元素组成的列表。通过处理和组合每个列表中的元素,我必须为字典中的每个元素生成一个输出列表。

所有的列表都可以独立分析,所以这个设置应该很容易并行。

下面是我用于pool.map的基本设置:

代码语言:javascript
复制
from multiprocessing.dummy import Pool as ThreadPool

pool   = ThreadPool(NUM_THREADS)
output = pool.map(thread_compute, iterable_list)
pool.close()
pool.join
  • 方法1(错误):将字典定义为全局并让每个线程获取字典的一个键为input.in,主全局input_dict iterable_list = input_dict.keys() # thread_compute函数def thread_compute(key_i):list_to_combine = input_dictkey_i # call a function processed_list = do_stuff_function(list_to_combine)返回processed_list

我很快意识到,方法1将无法工作,因为它是全局变量input_dict,尽管它从未为写操作进行访问(因此应该是线程安全的),但它受到GIL (链接1链接2)的保护--在尝试从独立线程中安全地访问Python对象时,这是一种全局强制的锁。

  • 方法2(不起作用):我创建了一个包含与input_dict相同的元素的列表,其中每个条目都是一个包含25个条目的列表。这个列表不是一个全局变量,每个线程都应该能够访问一个元素(一个25项列表),而不需要任何开销,这是由于GIL.in --主项= list(input_dict.items()) iterable_list = [itemsi for i in range(len( items ))] ##确保内容正确地断言(len(Iterable_list) == len(input_dict))在xrange中(len(input_dict.keys():assert(iterable_listi == input_dict[input_ )]dict.keys()i]) # thread_compute函数def thread_compute(list_of_25_i):#调用函数processed_list = do_stuff_function(list_of_25_i)返回processed_list

以下是1、2、4和16个线程的执行时间:

代码语言:javascript
复制
   1:  Done, (t=36.6810s).
   2:  Done, (t=46.5550s).
   4:  Done, (t=48.2722s).
   16: Done, (t=48.9660s).

为什么添加线程会导致时间的增加?我确信这个问题可以从多线程中受益,并且认为添加线程的开销不能单独负责增加。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-09-27 15:53:54

如果您的do_stuff_function是CPU绑定的,那么在多个线程中运行它不会有帮助,因为GIL只允许一次执行一个线程。

在Python中,解决这个问题的方法是使用多个进程,只需替换

代码语言:javascript
复制
from multiprocessing.dummy import Pool

使用

代码语言:javascript
复制
from multiprocessing import Pool
票数 2
EN

Stack Overflow用户

发布于 2016-09-27 15:57:49

尝试使用Pool (文档),因为它使用processes而不是threads

  • Python中的线程是concurrent,而不是parallel,这基本上意味着解释器将在执行多个线程之间非常快地切换,而在执行一个线程时,锁定所有其他线程的解释器,从而给人以并行运行操作的印象。
  • 另一方面,就时间而言,进程的生成成本要高得多,因为它们基本上是解释器的自己的实例,它们操作的数据必须序列化,并从主进程发送到工作进程。在那里,它被反序列化,计算,结果被序列化,并被再次发回。

但是,考虑到您发布的处理时间适中,生成进程所需的时间可能会对总体性能产生负面影响。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39728974

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档