在 Python 3 中确定 max_workers 用于多处理的最佳值的好方法是啥?
Posted
技术标签:
【中文标题】在 Python 3 中确定 max_workers 用于多处理的最佳值的好方法是啥?【英文标题】:What is a good way to determine the optimal value of max_workers for multi-processing in Python 3?在 Python 3 中确定 max_workers 用于多处理的最佳值的好方法是什么? 【发布时间】:2020-10-22 15:38:23 【问题描述】:我有一个用于自动化的 Python 脚本。它运行系统命令并将结果存储在数据库中。它包含以下行:
ThreadPoolExecutor(max_workers = 3)
我不知道将 max_workers 设置为什么值。我见过有人说max_workers的最优值?我听说人们说这取决于机器,但没有进一步详细说明。我还读到 Python 3 中的默认值是处理器数量 * 5。如果没有普遍最优的解决方案,那么有什么好方法可以接近这个问题的局部最优解决方案?
【问题讨论】:
【参考方案1】:Brian Goetz 在他的名著《Java Concurrency in Practice》中推荐了以下公式:
线程数 = 可用内核数 * (1 + 等待时间 / 服务时间)
等待时间 - 等待 IO 绑定任务完成所花费的时间,例如等待来自远程服务的 HTTP 响应。
(不仅是IO绑定的任务,可能是等待获得监视器锁的时间或线程处于WAITING/TIMED_WAITING状态的时间)
服务时间 - 是忙于处理 HTTP 响应、编组/解组、任何其他转换等的时间。
等待时间/服务时间 - 这个比率通常称为阻塞系数。
计算密集型任务的阻塞系数接近 0,在这种情况下,线程数等于可用内核数。如果所有任务都是计算密集型的,那么这就是我们所需要的。拥有更多线程无济于事。
例如:
工作线程调用微服务,将响应序列化为 JSON 并执行一些规则。微服务响应时间为50ms,处理时间为5ms。我们将应用部署到具有双核 CPU 的服务器上:
2 * (1 + 50 / 5) = 22 // 最佳线程池大小
但是这个例子过于简单了。除了 HTTP 连接池之外,您的应用程序可能还有来自 JMS 的请求,并且可能还有 JDBC 连接池。
如果您有不同类别的任务,最好使用多个线程池,这样每个线程池都可以根据其工作负载进行调整。
全文你可以找到here
【讨论】:
【参考方案2】:试试
import os
max_workers = os.cpu_count()
【讨论】:
这只是告诉我计算机的逻辑处理器数量,即 8。将其设置为该值似乎不是最佳值,因为 max_workers 的默认值为 8 * 5,这是一个不仅仅是 8 个。 我建议的是当前实践中的locally optimal
解决方案。实际数字取决于您要执行的任务,当然,您可以对其进行调整。以上是关于在 Python 3 中确定 max_workers 用于多处理的最佳值的好方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
在 Python 中使用 ProcessPoolExecutor 的运行调用数不正确