首页 > 解决方案 > 运行多处理时如何设置适当的池数量

问题描述

我正在尝试使用多处理运行网络抓取工具。我在理解适当数量的池时遇到了一些问题。我应该使用池数作为标准cpu_count()吗?

我的代码是这样的:

def experiment(df,n):
    with Pool(n) as p:
        results = p.map(ind_scraper_iterator, df)
    return(results)

df是一个字典列表(长度在3K左右),该ind_scraper_iterator函数使用字典中的字段从网络上查询和抓取。我尝试设置n为 600 和 700,但我收到一条错误消息BlockingIOError: [Errno 35] Resource temporarily unavailable。我认为这是因为池的数量,我想选择合适的数量,这样我就不会被阻止。

标签: pythonpython-3.xweb-scrapingmultiprocessingpython-multiprocessing

解决方案


在受 CPU 限制的用例中,是的,您希望池大小不大于可用 CPU 内核的数量。如果您在您Poolcpu_count(). 一旦池中的进程多于 CPU,实际上最终会损害性能,因为操作系统必须在额外进程之间进行上下文切换,以便它们都获得一些 CPU 时间,这会增加开销。

唯一一个你希望你的进程Pool比你拥有的 CPU 内核更多的情况是,如果你在进程中所做的工作是 I/O 密集型的,并且大部分时间都在阻塞,等待 I/O 完成. 等待 I/O 不使用任何 CPU 资源,因此您可以在不降低回报的情况下扩展可用的 CPU 内核数量。

在您的用例中,您正在进行网络抓取,这确实涉及 I/O(从网络获取数据)。我对细节的了解不够,无法知道是否有足够的 I/O(与您在获取数据后所做的任何其他事情相比)来证明池大于cpu_count()或不。您必须自己进行测试才能找到最佳位置。我会说 600-700 个进程可能太多了,仅仅是因为运行一个进程会产生相当多的内存开销,并且可能会使系统过载。如果您的用例结果是 I/O 密集型,您可能只想使用线程池,因为 I/O 可以仅使用线程有效地并行化。只有受 CPU 限制的工作不会释放无法在 (C)Python 中并行化的 GIL。您可能会发现让少量 CPU 工作序列化最终比让它并行运行更便宜,但必须处理由multiprocessing.

与往常一样,您需要进行自己的测试以确定最适合您的特定用例的方法。


推荐阅读