Python是否支持多线程?可以加快执行时间吗?

2020/12/07 00:32 · python ·  · 0评论

我对多线程是否可以在Python中工作感到有些困惑。

我知道对此有很多疑问,我已经阅读了很多,但是我仍然很困惑。我从自己的经验中知道,并且看到其他人在StackOverflow上发表了自己的答案和示例,说在Python中确实可以实现多线程。那么为什么每个人都说Python被GIL锁定并且一次只能运行一个线程呢?显然可以。还是我不来这里有什么区别?

许多张贴者/受访者还不断提到线程是有限的,因为它不使用多个核心。但是我会说它们仍然有用,因为它们可以同时工作,因此可以更快地完成合并的工作量。我的意思是为什么还要有Python线程模块呢?

更新:

到目前为止,感谢您提供所有答案。据我了解,多线程只能并行运行某些IO任务,而一次只能运行一个CPU绑定的多个核心任务。

我并不完全确定这对我实际上意味着什么,所以我仅举一个我想进行多线程的任务示例。例如,假设我要遍历很长的字符串列表,并且希望对每个列表项执行一些基本的字符串操作。如果我拆分列表,将每个要由我的循环/字符串代码处理的子列表发送到新线程中,然后将结果发送回队列中,这些工作负载是否会大致同时运行?最重要的是,从理论上讲,这会加快运行脚本的时间吗?

另一个例子可能是,如果我可以在四个不同的线程中使用PIL渲染和保存四张不同的图片,并且这比一张又一张地处理图片要快吗?我想这个速度要素是我真正想知道的,而不是正确的术语。

我也了解多处理模块,但是我现在的主要兴趣是中小型任务负载(10-30秒),因此我认为多线程将更合适,因为子进程的启动速度很慢。

GIL不会阻止线程化。GIL所做的全部工作就是确保一次只有一个线程在执行Python代码。控制仍然在线程之间切换。

GIL当时阻止的事情是利用多个CPU内核或单独的CPU并行运行线程。

这仅适用于Python代码。C扩展可以并且确实会发布GIL,以允许C代码的多个线程和一个Python线程跨多个内核运行。这扩展到由内核控制的I / O,例如select()对套接字读写的调用,使Python在多线程多核设置中合理有效地处理网络事件。

然后,许多服务器部署将执行多个Python进程,以使OS处理进程之间的调度,以最大程度地利用您的CPU内核。如果适合您的用例,您还可以使用该multiprocessing来处理来自一个代码库和父进程的多个进程的并行处理。

请注意,GIL仅适用于CPython实现。Jython和IronPython使用不同的线程实现(分别是本机Java VM和.NET公共运行时线程)。

直接解决更新问题:任何尝试使用纯Python代码从并行执行中提高速度的任务都不会看到加速,因为线程化的Python代码一次只能锁定一个线程。但是,如果混用C扩展名和I / O(例如PIL或numpy操作),则任何C代码都可以与一个活动的Python线程并行运行

Python线程非常适合创建响应式GUI或处理多个简短的Web请求,而I / O比Python代码更是瓶颈。它不适用于并行化计算量大的Python代码,不适合执行multiprocessing此类任务模块或委托给专用的外部库。

是。:)

您具有低级线程模块和高级线程模块。但是您只需要使用多核计算机,多处理模块就是您的理想之选。

文档引用

在CPython中,由于使用了全局解释器锁,因此只有一个线程可以一次执行Python代码(即使某些面向性能的库可以克服此限制)。如果希望您的应用程序更好地利用多核计算机的计算资源,建议您使用多处理。但是,如果您要同时运行多个I / O绑定任务,则线程化仍然是合适的模型。

Python允许线程化,唯一的问题是GIL将确保一次只执行一个线程(没有并行性)。

因此,基本上,如果您想对代码进行多线程处理以加快计算速度,那么一次只能执行一个线程就不会加快代码的处理速度,但是例如,如果您使用它与数据库进行交互,它就会加快速度。

我之所以喜欢张贴者,是因为答案总是“取决于您想做什么”。但是以我的经验,即使对于多处理,python中的并行速度也一直很糟糕。

例如,请查看本教程(在Google中排名第二):https : //www.machinelearningplus.com/python/parallel-processing-python/

我在此代码周围放置了时间,并增加了池映射函数的进程数(2、4、8、16),并得到了以下不良时间:

serial 70.8921644706279 
parallel 93.49704207479954 tasks 2
parallel 56.02441442012787 tasks 4
parallel 51.026168536394835 tasks 8
parallel 39.18044807203114 tasks 16

代码:#在开始时增加数组大小#我的计算节点有40个CPU,所以我在这里有很多备用

arr = np.random.randint(0, 10, size=[2000000, 600])
.... more code ....
tasks = [2,4,8,16]

for task in tasks:
    tic = time.perf_counter()
    pool = mp.Pool(task)

    results = pool.map(howmany_within_range_rowonly, [row for row in data])

    pool.close()
    toc = time.perf_counter()
    time1 = toc - tic
    print(f"parallel {time1} tasks {task}")
本文地址:http://python.askforanswer.com/pythonshifouzhichiduoxianchengkeyijiakuaizhixingshijianma.html
文章标签: ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!