ProcessPoolExecutor 以非直观的方式提高性能
ProcessPoolExecutor increase performance in non-intuitive way
我有一个基本上是多线程的应用程序:线程 1 是计算,线程 2 是 GUI (Tkinter)。计算的一部分包括一个带循环的函数。所以我决定在这里以这样的方式使用多处理:
def mpw1(idw_tree, mapsdata, inlines, xlines, x, y, dfattrs, calcplan, attrsdim, mdim):
n_cores = os.cpu_count()
flatcubec2 = np.zeros((attrsdim,mdim))
with ProcessPoolExecutor(n_cores) as ex:
args = ((i, calcplan, idw_tree, mapsdata, dfattrs, flatcubec2, inlines, xlines, n_cores) for i in range(n_cores))
flatcubec2 = ex.map(circle, args)
return flatcubec2
其中 circle
只是一个计算函数(假设它在计数)。
但奇怪的是,尽可能多地设置n_cores
并不能使我获得最佳性能。这是一些信息:
8 核(最大)- 17 秒
6 核 - 14 秒
4 核 - 12 秒
3 核 - 14 秒
2 核 - 17 秒
究竟是怎么回事?为什么使用最大的硬件不能获得最佳性能?我使用多线程的方式有问题吗?
首先,由于您使用的是 ProcessPoolExecutor
,它是 多处理,而不是 多线程。由于全局解释器锁,多线程在 Python 中几乎没有提供性能提升。
其次,如果不查看实际代码,就很难解释您的应用程序的性能。多处理涉及相当多的开销,因此只有当您有相当多的处理工作要做时(当然还有足够的可用内核来执行这些进程),它才有用。
从您发布的结果来看,似乎最多 4 个内核将工作负载分配给可用内核并获得了一些性能,但是当使用更多内核时,开销会增加到比增加处理时间。
此行为的原因是我使用了错误的命令 (multiprocessing.cpu_count()) 来设置要使用的进程数量,此命令 return 我比应有的多了两倍,在mp 必须只使用物理 cpu,不使用逻辑
因此,这种行为在第 4 个“worker”(在我的例子中是物理 cpu 的最大值)之后性能开始下降可以解释为多处理工作明确且可预测物理 cpu'只有。为了获得物理 cpu 的数量,我只使用了:
psutil.cpu_count(logical = False)
我有一个基本上是多线程的应用程序:线程 1 是计算,线程 2 是 GUI (Tkinter)。计算的一部分包括一个带循环的函数。所以我决定在这里以这样的方式使用多处理:
def mpw1(idw_tree, mapsdata, inlines, xlines, x, y, dfattrs, calcplan, attrsdim, mdim):
n_cores = os.cpu_count()
flatcubec2 = np.zeros((attrsdim,mdim))
with ProcessPoolExecutor(n_cores) as ex:
args = ((i, calcplan, idw_tree, mapsdata, dfattrs, flatcubec2, inlines, xlines, n_cores) for i in range(n_cores))
flatcubec2 = ex.map(circle, args)
return flatcubec2
其中 circle
只是一个计算函数(假设它在计数)。
但奇怪的是,尽可能多地设置n_cores
并不能使我获得最佳性能。这是一些信息:
8 核(最大)- 17 秒
6 核 - 14 秒
4 核 - 12 秒
3 核 - 14 秒
2 核 - 17 秒
究竟是怎么回事?为什么使用最大的硬件不能获得最佳性能?我使用多线程的方式有问题吗?
首先,由于您使用的是 ProcessPoolExecutor
,它是 多处理,而不是 多线程。由于全局解释器锁,多线程在 Python 中几乎没有提供性能提升。
其次,如果不查看实际代码,就很难解释您的应用程序的性能。多处理涉及相当多的开销,因此只有当您有相当多的处理工作要做时(当然还有足够的可用内核来执行这些进程),它才有用。
从您发布的结果来看,似乎最多 4 个内核将工作负载分配给可用内核并获得了一些性能,但是当使用更多内核时,开销会增加到比增加处理时间。
此行为的原因是我使用了错误的命令 (multiprocessing.cpu_count()) 来设置要使用的进程数量,此命令 return 我比应有的多了两倍,在mp 必须只使用物理 cpu,不使用逻辑 因此,这种行为在第 4 个“worker”(在我的例子中是物理 cpu 的最大值)之后性能开始下降可以解释为多处理工作明确且可预测物理 cpu'只有。为了获得物理 cpu 的数量,我只使用了:
psutil.cpu_count(logical = False)