为啥我导入 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 模块(numpyscipytablespandasskimage...)在导入时会混淆核心亲和力。据我所知,这个问题似乎是由它们链接到多线程 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亲和力的方法是use psutil @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

Both multiprocessing.map and joblib use only 1 cpu after upgrade from Ubuntu 10.10 to 12.04 Python multiprocessing utilizes only one core multiprocessing.Pool processes locked to a single core

我建议尝试 CPU 亲和性 (taskset)。

【讨论】:

Python on Ubuntu 这意味着它可以在 Windows 和其他操作系统上正常工作。是吗?

以上是关于为啥我导入 numpy 后多处理只使用一个核心?的主要内容,如果未能解决你的问题,请参考以下文章

使用 numpy 在 Python 中处理 TIFF(导入、导出)

为啥 cffi 比 numpy 快这么多?

为啥使用numpy和pandas来进行数据处理?

java为啥urlencode后多出%ef%bb%bf

选择后多选上升

Numpy 导入抛出 AttributeError:“模块”对象没有属性“核心”