了解python多处理池映射线程安全性



这个问题的答案相互矛盾:Python多处理池线程安全吗?

我是并发模式的新手,我正在尝试运行一个项目,该项目接收一个数组并将数组的工作分配到多个进程上。数组很大。

inputs = range(100000)
with Pool(2) as pool:
res = pool.map(some_func, inputs)

我的理解是,pool将把任务分配给流程。我的问题是:

  1. 这个映射操作线程安全吗?两个进程是否会意外地尝试处理相同的值
  2. 我表面上理解的是,任务会被分成块并发送到进程。然而,如果不同的输入比其他输入花费更多的时间,那么工作是否总是均匀地分布在我的流程中?我是否会遇到这样的情况:一个进程挂起,但在其他进程空闲时有一长串任务要做
  3. 我的理解是,由于我只是在读取输入,所以我不需要使用任何进程间通信模式,如服务器管理器/共享内存。是这样吗
  4. 如果我设置的进程比核心多,它基本上会像CPU在任务之间切换的线程一样运行吗

谢谢!

  1. 使用提供的代码,inputs的同一项不可能由多个进程处理(如果对象的同一实例在作为参数传递的迭代中出现多次,则会出现异常(。然而,这种使用多处理的方式有很多开销,因为inputs项目是一个接一个地发送给进程的。更好的方法是使用chunksize参数:
inputs = range(100000)
n_proc = 2
chunksize = len(inputs)//n_proc
if len(inputs) % n_proc:
chunksize += 1
with Pool(nproc) as pool:
res = pool.map(some_func, inputs, chunksize=chunksize)

通过这种方式,inputs的块一次传递给每个进程,从而获得更好的性能。

  1. 除非您提出要求,否则工作不会被划分为块。如果没有提供chunksize,则每个块都是可迭代项中的一项(相当于chunksize=1(。每个区块将被逐个"发送"到池中的可用进程。块在进程完成前一个块的工作并变得可用时被发送到进程。不需要每个进程都采用相同数量的块。在您的示例中,如果some_func的值越大,而chunksize = len(items)/2的值越长,则获取具有inputs前半部分(值越小(的块的过程将首先完成,而另一半则需要更长的时间。在这种情况下,较小的区块是更好的选择,因此工作是均匀分布的。

  2. 这取决于some_func的作用。如果不需要some_func(n)的结果来处理some_func(m),则不需要在进程之间进行通信。如果您正在使用map并且需要在进程之间进行通信,则很可能您在解决问题时采用了糟糕的方法。

  3. 如果max_workers > os.cpu_count(),则CPU将比具有较低数量的进程更频繁地在进程之间切换。不要忘记,在一台(并不令人惊讶的旧(计算机上运行的进程比你的程序多得多。在windows中,max_workers必须等于或小于61(请参阅此处的文档(

最新更新