Python 3多处理:最佳块大小

字节指挥官

如何找到multiprocessing.Pool实例的最佳块大小

我在创建n数独对象生成器之前使用了此方法

processes = multiprocessing.cpu_count()
worker_pool = multiprocessing.Pool(processes)
sudokus = worker_pool.imap_unordered(create_sudoku, range(n), n // processes + 1)

为了测量时间,我time.time()在上面的代码片段之前使用了它,然后按照说明初始化了池,然后将生成器转换为列表(list(sudokus))以触发生成项(仅用于时间测量,我知道这在最终程序中是无稽之谈),然后花时间time.time()再次使用并输出差值。

我观察到结果的块大小每个对象的n // processes + 1时间约为0.425毫秒但是我还观察到,CPU仅在进程的前半部分完全加载,最终使用率下降到25%(在具有2个内核和超线程的i3上)。

如果我使用较小的块大小int(l // (processes**2) + 1)代替,我得到的时间大约为0.355毫秒,并且CPU负载分配得更好。它只有一些小的尖峰,下降到大约 75%,但在下降到25%之前的较长时间内保持较高的状态。

有没有更好的公式来计算块大小,或者还有其他更好的方法来最有效地使用CPU?请帮助我提高此多处理池的效率。

最大限度

该答案提供了较高的概述。

进入detais时,每个工人每次都发送大量chunksize任务进行处理。工人每次完成该工作块时,都需要通过某种类型的进程间通信(IPC)(例如)来请求更多输入queue.Queue每个IPC请求都需要一个系统调用。由于上下文切换,它的成本在1到10 µs的范围内,比如说10 µs。由于共享缓存,上下文切换可能会(在一定程度上)损害所有内核。因此,非常悲观的是,我们估算IPC请求的最大可能开销为100μs。

您希望IPC开销不重要,例如<1%。如果我的数字正确,可以通过使块处理时间> 10 ms来确保。因此,如果每个任务要花1μs的时间来处理,那么您chunksize至少需要10000

不能chunksize任意增大的主要原因是,在执行结束时,其中一个工作人员可能仍在其他所有人完成工作的同时在运行-显然不必要地增加了完成工作的时间。我想在大多数情况下,延迟10 ms并不是什么大问题,所以我建议以10 ms的块处理时间为目标似乎是安全的。

大型设备chunksize可能引起问题的另一个原因是,准备输入内容可能会花费一些时间,同时浪费了工人的能力。大概输入准备比处理要快(否则,也应该使用RxPY之类的东西将其并行)。因此,再次将〜10 ms的处理时间作为目标似乎是安全的(假设您不介意10 ms以下的启动延迟)。

注意:对于现代Linux / Windows上的非实时进程,上下文切换大约每1-20毫秒发生一次-除非该进程当然早些进行系统调用。因此,如果不使用系统调用,上下文切换的开销将不超过〜1%。除此之外,由于IPC而造成的任何开销。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章