【问题标题】:Limit number of threads in numpy限制numpy中的线程数
【发布时间】:2015-06-11 21:12:19
【问题描述】:

似乎我的 numpy 库正在使用 4 个线程,设置 OMP_NUM_THREADS=1 并不能阻止这一点。

numpy.show_config() 给了我这些结果:

atlas_threads_info:
    libraries = ['lapack', 'ptf77blas', 'ptcblas', 'atlas']
    library_dirs = ['/usr/lib64/atlas']
    define_macros = [('ATLAS_INFO', '"\\"3.8.4\\""')]
    language = f77
    include_dirs = ['/usr/include']
blas_opt_info:
    libraries = ['ptf77blas', 'ptcblas', 'atlas']
    library_dirs = ['/usr/lib64/atlas']
    define_macros = [('ATLAS_INFO', '"\\"3.8.4\\""')]
    language = c
    include_dirs = ['/usr/include']
atlas_blas_threads_info:
    libraries = ['ptf77blas', 'ptcblas', 'atlas']
    library_dirs = ['/usr/lib64/atlas']
    define_macros = [('ATLAS_INFO', '"\\"3.8.4\\""')]
    language = c
    include_dirs = ['/usr/include']
openblas_info:
  NOT AVAILABLE
lapack_opt_info:
    libraries = ['lapack', 'ptf77blas', 'ptcblas', 'atlas']
    library_dirs = ['/usr/lib64/atlas']
    define_macros = [('ATLAS_INFO', '"\\"3.8.4\\""')]
    language = f77
    include_dirs = ['/usr/include']

所以我知道它使用的是 blas,但我不知道如何让它使用 1 个线程进行矩阵乘法。

【问题讨论】:

标签: python multithreading numpy


【解决方案1】:

尝试设置以下所有内容:

export MKL_NUM_THREADS=1
export NUMEXPR_NUM_THREADS=1
export OMP_NUM_THREADS=1

有时很难看出究竟在哪里引入了多线程。

【讨论】:

  • 这需要更多细节。
  • 在 Mac 上,export VECLIB_MAXIMUM_THREADS=1;请参阅 SO 上的performance-of-numpy-with-different-blas-implementations。注意:man Accelerate 表示“VECLIB_MAXIMUM_THREADS 的值可能会被库缓存并重用;如果需要确保单线程执行,则应在进行任何 Accelerate 调用之前设置 VECLIB_MAXIMUM_THREADS”
  • 从脚本中执行此操作的最佳方法是什么?我应该只运行os.system("export OMP_NUM_THREADS=1") 吗?我已经阅读了关于这是否会正常工作的混合评论,即使可以,这是最好的方法吗?出于某种原因,它似乎有点 hacky。
  • 对于和我上面有同样问题的其他人,根据这个线程http://numpy-discussion.10968.n7.nabble.com/Set-threads-from-within-python-code-td44108.html 你可以做os.environ["OMP_NUM_THREADS"] = "1" 等,但你必须把那个 before 你有@ 987654328@。显然 numpy 只在导入时检查这个。
  • @seth127 您应该将此作为 IMO 的答案,它很有用。
【解决方案2】:

有超过 3 个提到的环境变量。以下是环境变量的完整列表以及使用该变量来控制它产生的线程数的包。请注意,您需要在执行 import numpy 之前设置这些变量:

OMP_NUM_THREADS: openmp,
OPENBLAS_NUM_THREADS: openblas,
MKL_NUM_THREADS: mkl,
VECLIB_MAXIMUM_THREADS: accelerate,
NUMEXPR_NUM_THREADS: numexpr

所以在实践中你可以这样做:

import os
os.environ["OMP_NUM_THREADS"] = "4" # export OMP_NUM_THREADS=4
os.environ["OPENBLAS_NUM_THREADS"] = "4" # export OPENBLAS_NUM_THREADS=4 
os.environ["MKL_NUM_THREADS"] = "6" # export MKL_NUM_THREADS=6
os.environ["VECLIB_MAXIMUM_THREADS"] = "4" # export VECLIB_MAXIMUM_THREADS=4
os.environ["NUMEXPR_NUM_THREADS"] = "6" # export NUMEXPR_NUM_THREADS=6

请注意,从 2018 年 11 月起,Numpy 开发人员正在努力使这成为可能,您也可以在您执行 import numpy 之后执行此操作。他们提交这些更改后,我会更新这篇文章。

【讨论】:

  • 在某些集群上,我发现我需要在 shell 中进行导出,而 os.environ 不起作用。
  • @Amir 这些环境变量的 numpy 库是否已经有更新?
  • 您好,有什么更新吗?
【解决方案3】:

关于在 python 脚本中执行此操作,而不是在 bash 提示符下,根据 this thread,您可以执行以下操作(与上述答案相同的命令):

import os
os.environ["MKL_NUM_THREADS"] = "1" 
os.environ["NUMEXPR_NUM_THREADS"] = "1" 
os.environ["OMP_NUM_THREADS"] = "1" 

但是你必须把它放在之前你做import numpy显然numpy只在导入时检查这个。

(这是根据上面的@kηives 评论重新发布的答案。)

【讨论】:

  • 如果你已经链接到 OpenBLAS,我相信还有 OPENBLAS_NUM_THREADS。
  • 实际上,这不是在您导入 numpy 时设置的,而是在您首次调用 MKL 优化的 Numpy 代码时设置的。例如,np.ones() 不会触发读取这些变量,但 np.dot() 会触发。
【解决方案4】:

在没有运气的情况下尝试了上述一些解决方案后,我在 Numpy docs 中找到了对 threadpoolctl 的引用。这很有效,即使已经导入了 numpy,也可以使用它。

with threadpool_limits(limits=1, user_api='blas'):
  # single threaded numpy code...

请确保使用您在使用时列出的user_api

from threadpoolctl import threadpool_info
from pprint import pprint
import numpy
pprint(threadpool_info())

【讨论】:

  • 有没有办法在笔记本或脚本的开头设置一次?我不想更改我的代码库以将其部分包装在此上下文管理器中,并且我不想尝试将整个脚本包装在此 with 语句下(不适用于例如拆分的 iPython 笔记本多个单元格)。
【解决方案5】:

我能够在运行时通过以下方式解决此问题:

import mkl
mkl.set_num_threads(1)

我使用以下代码使这个 sn-p 不太可能导致脚本/包出现问题:

try:
    import mkl
    mkl.set_num_threads(1)
except:
    pass

【讨论】:

    猜你喜欢
    • 2012-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    相关资源
    最近更新 更多