为啥我导入 numpy 后多处理只使用一个核心?
Posted
技术标签:
【中文标题】为啥我导入 numpy 后多处理只使用一个核心?【英文标题】:Why does multiprocessing use only a single core after I import numpy?为什么我导入 numpy 后多处理只使用一个核心? 【发布时间】:2013-03-16 09:48:01 【问题描述】:我不确定这是否更多地被视为操作系统问题,但我想我会在这里问一下,以防有人对 Python 的结局有所了解。
我一直在尝试使用 joblib
并行化 CPU 密集型 for
循环,但我发现不是将每个工作进程分配给不同的核心,而是将它们全部分配给相同的内核,没有性能提升。
这是一个非常简单的例子......
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
正在为不同的工作人员生成单独的进程,但是有什么方法可以让这些进程在不同的内核上执行?
【问题讨论】:
***.com/questions/15168014/… - 恐怕没有答案,但听起来是同一个问题。 还有***.com/questions/6905264/… 还有***.com/questions/12592018/… 这仍然是个问题吗?我正在尝试使用 Python 3.7 重新创建它并使用 multiprocessing.Pool() 导入 numpy,它正在使用所有线程(应该如此)。只是想确保已解决此问题。 这是同一个问题吗? joblib.readthedocs.io/en/latest/… “一些第三方库——例如 numpy 使用的 BLAS 运行时——在内部管理一个线程池来执行它们的计算。……joblib 告诉支持的第三方库在由 ' 管理的工作线程中使用有限数量的线程loky' 后端……从 joblib 0.14 开始,还可以使用 parallel_backend 函数的 inner_max_num_threads 参数以编程方式覆盖默认线程数“ 【参考方案1】:经过一番谷歌搜索后,我找到了答案here。
事实证明,某些 Python 模块(numpy
、scipy
、tables
、pandas
、skimage
...)在导入时会混淆核心亲和力。据我所知,这个问题似乎是由它们链接到多线程 OpenBLAS 库引起的。
一种解决方法是使用
重置任务关联性os.system("taskset -p 0xff %d" % os.getpid())
在模块导入后粘贴此行,我的示例现在可以在所有内核上运行:
到目前为止,我的经验是,这似乎对 numpy
的性能没有任何负面影响,尽管这可能是特定于机器和任务的。
更新:
还有两种方法可以禁用 OpenBLAS 本身的 CPU 关联重置行为。在运行时可以使用环境变量OPENBLAS_MAIN_FREE
(或GOTOBLAS_MAIN_FREE
),例如
OPENBLAS_MAIN_FREE=1 python myscript.py
或者,如果您从源代码编译 OpenBLAS,您可以在构建时通过编辑 Makefile.rule
以包含该行来永久禁用它
NO_AFFINITY=1
【讨论】:
谢谢,您的解决方案解决了问题。一个问题,我有相同的代码,但在两台不同的机器上运行不同。两台机器都是 Ubuntu 12.04 LTS,python 2.7,但只有一台有这个问题。你知道为什么吗? 两台机器都有 OpenBLAS(使用 OpenMPI 构建)。 旧线程,但万一其他人发现这个问题,我遇到了确切的问题,它确实与 OpenBLAS 库有关。请参阅here 了解两种可能的解决方法和一些相关讨论。 另一种设置cpu亲和力的方法是usepsutil
。
@JHG 这是 OpenBLAS 而不是 Python 的问题,所以我看不出 Python 版本会产生影响的任何原因【参考方案2】:
Python 3 现在公开methods 以直接设置亲和力
>>> 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
【讨论】:
Error > AttributeError: module 'os' has no attribute 'sched_getaffinity' , Python 3.6 @Paddy 来自链接文档:它们仅在某些 Unix 平台上可用。 我有同样的问题,但我在顶部集成了同一行 os.system("taskset -p 0xff %d" % os.getpid()) 但它没有使用所有 cpu 我在集群上遇到了同样的问题。任何在计算节点上运行的 python 进程都只会使用 1 个内核,即使我的代码原则上能够使用更多内核,即使我请求了大约 20 个内核。对我来说,在我的 python 代码中添加 import os 和 os.sched_setaffinity(0,range(1000)) 解决了这个问题。【参考方案3】:这似乎是 Ubuntu 上 Python 的常见问题,并非特定于 joblib
:
我建议尝试 CPU 亲和性 (taskset
)。
【讨论】:
Python on Ubuntu
这意味着它可以在 Windows 和其他操作系统上正常工作。是吗?以上是关于为啥我导入 numpy 后多处理只使用一个核心?的主要内容,如果未能解决你的问题,请参考以下文章