python多线程加速for循环_多线程-如何在Python的循环中对操
作进⾏多线程
⾸先,在Python中,如果您的代码受CPU约束,那么多线程将⽆济于事,因为只有⼀个线程可以持有全局解释器锁,因此⼀次只能运⾏Python代码。 因此,您需要使⽤进程,⽽不是线程。
如果您的操作“永远需要返回”是因为它是IO绑定的,也就是说,正在等待⽹络或磁盘副本等,这是不正确的。 我稍后再讲。
接下来,⼀次处理5个或10个或100个项⽬的⽅法是创建5个或10个或100个⼯⼈的池,并将这些项⽬放⼊由⼯⼈服务的队列中。 幸运的是,stdlib multiprocessing和ProcessPoolExecutor库都为您提供了⼤部分详细信息。
前者在传统编程⽅⾯更强⼤,更灵活。 如果您需要编写将来的等待,则后者更简单; 对于微不⾜道的情况,选择哪⼀个并不重要。 (在这种情况下,最明显的实现分别是3⾏与ProcessPoolExecutor,4⾏与ThreadPoolExecutor。)
如果您使⽤的是2.6-2.7或3.0-3.1,则没有内置ProcessPoolExecutor,但您可以从PyPI(ThreadPoolExecutor)安装它。
最后,如果您可以将整个循环迭代转换为函数调⽤(通常可以将其传递给ProcessPoolExecutor),那么并⾏化处理通常会容易得多,所以让我们⾸先进⾏以下操作:
def try_my_operation(item):
try:
<_operation(item)
except:
print('error with item')
放在⼀起:
executor = concurrent.futures.ProcessPoolExecutor(10)
futures = [executor.submit(try_my_operation, item) for item in items]
concurrent.futures.wait(futures)
python代码转换如果您有很多相对较⼩的⼯作,则多处理的开销可能会浪费收益。 解决该问题的⽅法是将⼯作分批处理成更⼤的⼯作。 例如(使⽤ProcessPoolExecutor872⾷谱中的ProcessPoolExecutor,您可以将其复制并粘贴到您的代码中,或者从PyPI上的ThreadPoolExecutor项⽬获得):
def try_multiple_operations(items):
for item in items:
try:
<_operation(item)
except:
print('error with item')
executor = concurrent.futures.ProcessPoolExecutor(10)
futures = [executor.submit(try_multiple_operations, group)
for group in grouper(5, items)]
concurrent.futures.wait(futures)
最后,如果您的代码受IO约束怎么办? 这样线程就和进程⼀样好,并且开销更少(限制更少,但是在这种情况下这些限制通常不会影响您)。 有时,“较少的开销”⾜以表⽰您不需要使⽤线程进⾏批处理,但是您需要使⽤进程,这是⼀个不错的选择。
那么,如何使⽤线程⽽不是进程? 只需将ProcessPoolExecutor更改为ThreadPoolExecutor。
如果不确定代码是受CPU约束还是受IO约束,只需尝试两种⽅法即可。
我可以在python脚本中为多个功能执⾏此操作吗? 例如,如果我要并⾏化的代码中其他地⽅有另⼀个for循环。 是否可以在同⼀脚本中执⾏两个多线程函数?
是。 实际上,有两种不同的⽅法可以做到这⼀点。
⾸先,您可以共享同⼀(线程或进程)执⾏程序,并可以在多个地⽅使⽤它⽽没有问题。 任务和未来的重点在于它们是独⽴的。 您不在乎它们在哪⾥运⾏,只需将它们排队并最终得到答案即可。
或者,您可以在同⼀个程序中有两个执⾏程序,没有问题。 这会降低性能,如果您同时使⽤两个执⾏器,最终将试图在8个内核上运⾏(例如)16个繁忙线程,这意味着将需要进⾏⼀些上下⽂切换。 但
是有时候这样做是值得的,因为,例如,两个执⾏器很少同时忙,这会使您的代码更加简单。 也许⼀个执⾏程序正在运⾏可能需要⼀段时间才能完成的⾮常⼤的任务,⽽另⼀个执⾏程序却正在运⾏需要尽快完成的⾮常⼩的任务,因为响应能⼒⽐部分程序的吞吐量更重要。
如果您不知道哪个适合您的程序,通常是第⼀个。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论