这个问题的答案相互矛盾:Python多处理池线程安全吗?
我是并发模式的新手,我正在尝试运行一个项目,该项目接收一个数组并将数组的工作分配到多个进程上。数组很大。
inputs = range(100000)
with Pool(2) as pool:
res = pool.map(some_func, inputs)
我的理解是,pool将把任务分配给流程。我的问题是:
- 这个映射操作线程安全吗?两个进程是否会意外地尝试处理相同的值
- 我表面上理解的是,任务会被分成块并发送到进程。然而,如果不同的输入比其他输入花费更多的时间,那么工作是否总是均匀地分布在我的流程中?我是否会遇到这样的情况:一个进程挂起,但在其他进程空闲时有一长串任务要做
- 我的理解是,由于我只是在读取输入,所以我不需要使用任何进程间通信模式,如服务器管理器/共享内存。是这样吗
- 如果我设置的进程比核心多,它基本上会像CPU在任务之间切换的线程一样运行吗
谢谢!
- 使用提供的代码,
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
的块一次传递给每个进程,从而获得更好的性能。
除非您提出要求,否则工作不会被划分为块。如果没有提供
chunksize
,则每个块都是可迭代项中的一项(相当于chunksize=1
(。每个区块将被逐个"发送"到池中的可用进程。块在进程完成前一个块的工作并变得可用时被发送到进程。不需要每个进程都采用相同数量的块。在您的示例中,如果some_func
的值越大,而chunksize = len(items)/2
的值越长,则获取具有inputs
前半部分(值越小(的块的过程将首先完成,而另一半则需要更长的时间。在这种情况下,较小的区块是更好的选择,因此工作是均匀分布的。这取决于
some_func
的作用。如果不需要some_func(n)
的结果来处理some_func(m)
,则不需要在进程之间进行通信。如果您正在使用map
并且需要在进程之间进行通信,则很可能您在解决问题时采用了糟糕的方法。如果
max_workers > os.cpu_count()
,则CPU将比具有较低数量的进程更频繁地在进程之间切换。不要忘记,在一台(并不令人惊讶的旧(计算机上运行的进程比你的程序多得多。在windows中,max_workers
必须等于或小于61(请参阅此处的文档(