为什么在我导入numpy之后多处理只使用一个核心?

我不确定这是否会成为一个操作系统问题,但我想我会问在这里,以防有人从Python的一端有所了解。

我一直在尝试使用joblib来并行执行一个CPU joblib循环,但是我发现,不是每个工作进程被分配到不同的内核,而是最终将所有这些进程分配给相同的内核,而且性能没有提高。

这是一个非常微不足道的例子…

 from joblib import Parallel,delayed import numpy as np def testfunc(data): # some very boneheaded CPU work for nn in xrange(1000): for ii in data[0,:]: for jj in data[1,:]: ii*jj def run(niter=10): data = (np.random.randn(2,100) for ii in xrange(niter)) pool = Parallel(n_jobs=-1,verbose=1,pre_dispatch='all') results = pool(delayed(testfunc)(dd) for dd in data) if __name__ == '__main__': run() 

…这是我在脚本运行时在htop看到的内容:

HTOP

我正在用4核心的笔记本电脑上运行Ubuntu 12.10(3.5.0-26)。 显然, joblib.Parallel是为不同的工作人员产生不同的进程,但是有什么办法可以让这些进程在不同的核心上执行?

经过一些更多的search之后,我在这里find了答案。

事实certificate,某些Python模块( numpyscipytablespandasskimage …)与导入时的核心skimage 。 据我所知,这个问题似乎是由他们链接到multithreading的OpenBLAS库特别造成的。

解决方法是使用重置任务亲和力

 os.system("taskset -p 0xff %d" % os.getpid()) 

在模块导入之后粘贴这行代码,我的示例现在可以在所有核心上运行:

htop_workaround

我的经验迄今为止,这似乎没有任何负面影响numpy的performance,虽然这可能是机器和任务的具体情况。

更新:

还有两种方法可以禁用OpenBLAS本身的CPU关联重置行为。 在运行时,您可以使用环境variablesOPENBLAS_MAIN_FREE (或GOTOBLAS_MAIN_FREE ),例如

 OPENBLAS_MAIN_FREE=1 python myscript.py 

或者,如果您从源代码编译OpenBLAS,您可以在编译时通过编辑Makefile.rule来永久禁用它,以包含行

 NO_AFFINITY=1 

Python 3现在公开了直接设置亲和力的方法

 >>> import os >>> os.sched_getaffinity(0) {0, 1, 2, 3} >>> os.sched_setaffinity(0, {1, 3}) >>> os.sched_getaffinity(0) {1, 3} >>> x = {i for i in range(10)} >>> x {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} >>> os.sched_setaffinity(0, x) >>> os.sched_getaffinity(0) {0, 1, 2, 3} 

这似乎是Ubuntu上的Python的一个常见问题,并不特定于joblib

  • 从ubuntu 10.10升级到12.04之后,multiprocessing.map和joblib只使用1个CPU
  • Python多处理只使用一个核心
  • 多进程。池进程locking到一个单一的核心

我会build议尝试CPU亲和力( taskset )。