【问题标题】:Time-intensive collection processing in PythonPython中耗时的集合处理
【发布时间】:2017-12-18 00:55:32
【问题描述】:

代码已经大大简化,但应该可以用来说明我的问题。

S = ('A1RT', 'BDF7', 'CP09')
for s in S:
    if is_valid(s): # very slow!
        process(s)

我有一个从网站抓取中获得的字符串集合。 (字符串将定期从站点抓取中检索。)这些字符串中的每一个都需要通过网络针对第三方进行验证。验证过程有时会很慢,这是有问题的。由于上述代码的迭代性质,可能需要一些时间才能验证和处理最后一个字符串。

是否有适当的方法在 Python 中并行化上述逻辑?坦率地说,我对并发/并行处理概念不是很熟悉,但在这种情况下它们似乎很有用。想法?

【问题讨论】:

标签: python python-3.x concurrency parallel-processing


【解决方案1】:

concurrent.futures 模块是解决“令人尴尬的并行”问题的好方法,并且可以很容易地在使用多个进程或单个进程中的多个线程之间切换。

在您的情况下,听起来“艰苦的工作”正在网络上的其他机器上完成,您的主程序将花费大部分时间等待它们提供结果。如果是这样,线程应该可以正常工作。这是一个完整的可执行玩具示例:

import concurrent.futures as cf

def is_valid(s):
    import random
    import time
    time.sleep(random.random() * 10)
    return random.choice([False, True])

NUM_WORKERS = 10  # number of threads you want to run

strings = list("abcdefghijklmnopqrstuvwxyz")

with cf.ThreadPoolExecutor(max_workers=NUM_WORKERS) as executor:
    # map a future object to the string passed to is_valid
    futures = {executor.submit(is_valid, s): s for s in strings}
    # `as_complete()` returns results in the order threads
    # complete work, _not_ necessarily in the order the work
    # was passed out
    for future in cf.as_completed(futures):
        result = future.result()
        print(futures[future], result)

这是一次运行的示例输出:

g False
i True
j True
b True
f True
e True
k False
h True
c True
l False
m False
a False
s False
v True
q True
p True
d True
n False
t False
z True
o True
y False
r False
w False
u True
x False

concurrent.futures 处理所有令人头疼的问题:启动线程、分配工作让它们完成,以及注意线程何时交付结果。

如上所述,最多可以同时激活 10 个 (NUM_WORKERS) is_valid() 调用。 as_completed() 在其结果准备好检索时立即返回一个未来对象,executor 自动将计算结果的线程交给另一个字符串供is_valid() 细嚼慢咽。

【讨论】:

  • 出于好奇,如果“辛勤工作”和等待时间是由于本地计算会发生什么?是否需要不同的方法?如果是这样,为什么?很抱歉所有问题,但我在这方面有点新手。
  • 并行处理是一个非常庞大和复杂的主题,已经写了很多书。如果您已经全职工作了一年,那么您仍然是“新手”;-) 也就是说,由于全局解释器锁定,线程对于纯 CPython 代码中的 CPU 密集型任务无效(Google on "蟒蛇吉尔”)。在这种情况下,您最好的第一个选择是使用 cf 的 ProcessPoolExecutor 代替(使用多个进程而不是多个线程,这样 GIL 就不再是问题了)。
  • 啊,非常感谢您的帮助/洞察力!我得问一下,你个人有什么资源可以推荐来开始这个主题吗?
  • @kylemart 很抱歉介入。在深入了解大量细节之前,您应该始终首先确定“公正”的区别-@987654331 @ 系统操作模式(调度)和真正的-[PARALLEL] 系统操作。这远远不一样。 下一个 应该永远,没有例外,没有借口,知道多线程/多进程或任何其他形式的处理并发的成本,可以选择加入。在不知道成本的情况下,人们可以花费与纯-[SERIAL] 处理流程相比,最终性能更差的巨大努力。
  • 问错人了。自 1980 年代以来,我一直在这样做,当时每个人都通过口耳相传和泪水相互学习;-) 我不知道现在以介绍性材料的方式可以获得什么。但是好的建议:除非您想为其他人实现并行处理噱头,否则请坚持使用您的语言提供的最高级别的抽象。这就是为什么我引导您使用concurrent.futures(Python 的最高级别并行抽象)。您可以从cf 如何实现中学到很多东西——但对于大多数人来说,这将是非常无用的底层知识。
猜你喜欢
  • 1970-01-01
  • 2019-11-22
  • 1970-01-01
  • 2017-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-01
相关资源
最近更新 更多