我有一个在Windows上运行的程序,它使用Python的多处理模块将计算分块到n_core
块,然后使用map_async
在单独的处理器上运行每个块。我注意到我没有按核心数量线性扩展。几个计算量很大的方法调用,我包含一个小计时功能,只考虑计算而不是设置和拆卸,并注意到它们实际上在并行运行中需要更长的时间。换句话说,虽然整个wallclock时间随着内核数量的增加而减少,但cpu时间(应该相当恒定)却在增加。对于串行代码路径和并行代码路径,这些定时器的调用方式相同。
一种这样的方法,串行总共花了10秒钟,但在分解并在4个核心上运行时总计接近20秒,通过内存映射文件(使用mmap
模块)读取数组数据并将数据的子集拉入cython中的模块变量c指针数组中。访问数据是相当随机的。如果我在sleep
调用的方法中插入一个长map_async
的随机长度,这样每个进程在其他进程休眠或完成时完成它的块,我恢复10秒的总计时。奇怪的是,如果我连续快速启动4次串行运行,我发现在每种方法中运行此方法所需的时间有所减少,但它并不像我在执行多处理代码时那么糟糕(可能是12 -13秒)。
这似乎表明在进程尝试读取memmapped文件时,进程之间存在某种冲突。这应该是一个瓶颈吗?这可能是一个Windows问题(我不在这个平台上做很多开发)?我只是在每个方向上一次发送和返回每个进程的数据,所以这不是典型的通信/酸洗开销问题。
对于此处可能发生的事情的建议,或者如何深入了解这一点,我们将不胜感激。在每个流程中运行cProfile
并没有提出任何明显的建议。不幸的是,代码很复杂,我无法在这里发布自包含的示例。
更新:我在OSX上看到了相同的行为,因此它不是特定于平台的问题
更新#2 :如果我快速连续运行4个串行作业,但每个只执行1个数据块的计算,那么我在多处理环境之外看到相同的~2x减速。奇怪的是,正如我之前提到的,如果我启动4个处理整个数据集的串行作业,那么每个作业只会减慢10-20%。所以这不是一个多处理问题。标题改为反映这一点。