为什么在我导入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
看到的内容:
我正在用4核心的笔记本电脑上运行Ubuntu 12.10(3.5.0-26)。 显然, joblib.Parallel
是为不同的工作人员产生不同的进程,但是有什么办法可以让这些进程在不同的核心上执行?
经过一些更多的search之后,我在这里find了答案。
事实certificate,某些Python模块( numpy
, scipy
, tables
, pandas
, skimage
…)与导入时的核心skimage
。 据我所知,这个问题似乎是由他们链接到multithreading的OpenBLAS库特别造成的。
解决方法是使用重置任务亲和力
os.system("taskset -p 0xff %d" % os.getpid())
在模块导入之后粘贴这行代码,我的示例现在可以在所有核心上运行:
我的经验迄今为止,这似乎没有任何负面影响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
)。