Python 多处理池.map按一定顺序调用函数

Python 多处理池.map按一定顺序调用函数,python,parallel-processing,multiprocessing,map-function,Python,Parallel Processing,Multiprocessing,Map Function,如何使multiprocessing.pool.map以数字顺序分布进程 更多信息: 我有一个程序,可以处理几千个数据文件,并对每个文件进行绘图。我使用multiprocessing.pool.map将每个文件分发给处理器,效果非常好。有时这需要很长时间,在程序运行时查看输出图像会很好。如果映射过程按顺序分发快照,这将容易得多;相反,对于我刚刚执行的特定运行,分析的前8个快照是:0、78、156、234、312、390、468、546。有没有办法使它们以数字顺序更紧密地分布在一起 示例: 下

如何使multiprocessing.pool.map以数字顺序分布进程


更多信息:
我有一个程序,可以处理几千个数据文件,并对每个文件进行绘图。我使用
multiprocessing.pool.map
将每个文件分发给处理器,效果非常好。有时这需要很长时间,在程序运行时查看输出图像会很好。如果映射过程按顺序分发快照,这将容易得多;相反,对于我刚刚执行的特定运行,分析的前8个快照是:
0、78、156、234、312、390、468、546
。有没有办法使它们以数字顺序更紧密地分布在一起


示例:
下面是一个示例代码,其中包含相同的关键元素,并显示相同的基本结果:

import sys
from multiprocessing import Pool
import time

num_proc  = 4; num_calls = 20; sleeper   = 0.1

def SomeFunc(arg):
    time.sleep(sleeper)
    print "%5d" % (arg),
    sys.stdout.flush()     # otherwise doesn't print properly on single line

proc_pool = Pool(num_proc)
proc_pool.map( SomeFunc, range(num_calls) )
收益率:

   0  4  2  6   1   5   3   7   8  10  12  14  13  11   9  15  16  18  17  19

答复: 从@Hayden开始:使用'chunksize'参数,
defmap(self、func、iterable、chunksize=None)

更多信息
chunksize
确定每次分配给每个处理器的迭代次数。例如,我上面的例子使用了chunksize为2,这意味着每个处理器在函数的2次迭代中停止工作,然后返回以获取更多(“签入”)。chunksize背后的权衡是,当处理器必须与其他处理器同步时,“签入”会有开销——这表明您需要一个大chunksize。另一方面,如果您有大的块,那么一个处理器可能会完成它的块,而另一个处理器还有很长的时间——因此您应该使用小的chunksize。我想额外有用的信息是有多少范围,每个函数调用可以花多长时间。如果它们真的需要相同的时间,那么使用较大的块大小会更有效。另一方面,如果某些函数调用的时间可能是其他函数调用的两倍,那么您需要一个较小的chunksize,这样处理器就不会被抓到等待


对于我的问题,每个函数调用都应该花费非常接近相同的时间(我认为),因此如果我希望按顺序调用进程,我将牺牲效率,因为签入开销。

map
更改为
imap

import os
from multiprocessing import Pool
import time

num_proc = 4
num_calls = 20
sleeper = 0.1

def SomeFunc(arg):
    time.sleep(sleeper)
    print "%s %5d" % (os.getpid(), arg)
    return arg

proc_pool = Pool(num_proc)
list(proc_pool.imap(SomeFunc, range(num_calls)))

原因可能是
imap
的默认
chunksize
为1,因此它可能不会运行到
map
为止。出现这种情况的原因是,每个进程在调用map开始时都有预定义的工作量要做,这取决于
chunksize
。通过查看源代码,我们可以计算出默认的
chunksize

因此,对于20的范围,以及4个进程,我们将获得2的
chunksize

如果我们修改您的代码以反映这一点,我们将得到与您现在得到的结果类似的结果:

proc\u pool.map(SomeFunc,range(num\u调用),chunksize=2)

这将产生以下输出:

02641753810141391151118181719

现在,设置
chunksize=1
将确保池中的每个进程一次只分配一个任务

proc\u pool.map(SomeFunc,range(num\u调用),chunksize=1)

与未指定chunksize时相比,这应确保合理良好的数字顺序。例如,chunksize为1会产生以下输出:


0 1 2 3 4 5 6 7 9 10 8 11 12 15 14 16 17 19 18

你用什么来绘制数据?@Satoru.Logic我不知道它有什么关系,但从内部
SomeFunc
我会调用另一个函数,例如
PlotFunc()
生成带有
matplotlib
pyplot
的图像,并将其保存到磁盘。是否可以并行进行一些预处理,然后按顺序打印?啊,我明白了-不太可能,大部分的计算时间只是在读取文件,所以我必须等待90%的总时间才能完成绘图。太棒了!谢谢你对他们为什么选择这种chunksize算法有什么见解吗?或者一般来说,性能优化应该考虑哪些因素?(就我而言,chunksize似乎不会对性能产生任何影响)我能问个问题吗?通过设置chuncksize=1,此pool.map函数是否同时运行算法?或者它只会解雇少数工人,但他们会有条不紊地做事?我不太理解文档中的“块”。。
chunksize, extra = divmod(len(iterable), len(self._pool) * 4)
if extra:
  chunksize += 1