限制"threads"个数时设置什么?
What am I setting when I limit the number of "threads"?
我有一段使用库 numpy, scipy, sklearn, matplotlib
的大型代码。我需要限制 CPU 的使用以阻止它消耗我的计算集群中的所有可用处理能力。在 this answer 之后,我实现了以下代码块,该代码块在脚本为 运行:
时立即执行
import os
parallel_procs = "4"
os.environ["OMP_NUM_THREADS"] = parallel_procs
os.environ["MKL_NUM_THREADS"] = parallel_procs
os.environ["OPENBLAS_NUM_THREADS"] = parallel_procs
os.environ["VECLIB_MAXIMUM_THREADS"] = parallel_procs
os.environ["NUMEXPR_NUM_THREADS"] = parallel_procs
我的理解是这应该将使用的核心数限制为 4,但显然这并没有发生。这是 htop
为我的用户和脚本显示的内容:
有 16 个进程,其中 4 个 CPU 的百分比显示在 100% 以上。这是 lscpu
:
的摘录
CPU(s): 48
On-line CPU(s) list: 0-47
Thread(s) per core: 2
Core(s) per socket: 12
Socket(s): 2
我还在我的代码中使用 multiprocessing
库。我使用 multiprocessing.Pool(processes=4)
设置了相同数量的进程。如果没有上面显示的代码块,脚本坚持使用尽可能多的内核,显然完全忽略了 multiprocessing
。
我的问题是:当我使用上面的代码时,我限制了什么?我应该如何解释 htop
输出?
(作为评论可能更好,如果出现更好的答案,请随时删除它,因为它基于我使用库的经验。)
我在多处理部分代码时遇到了类似的问题。如果您使用 BLAS 或 MKL 编译库(或者如果您从中提取它们的 conda repo 还包含 BLAS/MKL 库),以加速某些计算。
当 运行 您的脚本在单个进程中时,这很好,因为它会产生线程数达到 OPENBLAS_NUM_THREADS
或 MKL_NUM_THREADS
指定的数量(取决于您是否有BLAS 库或 MKL 库 - 您可以使用 numpy.__config__.show()
) 来识别哪个在这种情况下,设置 n=1
(before importing numpy & scipy)或一些小数字以确保您没有超额订阅是有意义的:
n = '1'
os.environ["OMP_NUM_THREADS"] = n
os.environ["MKL_NUM_THREADS"] = n
如果设置multiprocessing.Pool(processes=4)
,它将使用4*n
个进程(每个进程中有n
个线程)。在您的情况下,您似乎有一个包含 4 个进程的池,每个进程启动 4 个线程,因此有 16 个 python 个进程。
htop
输出给出 。由于 Linux 机器将线程解释为 CPU(我这里的术语可能有误),如果每个 CPU 有 4 个线程,则意味着满载实际上是 400 %。这可能不会达到最大值,具体取决于正在执行的操作(以及缓存,因为您的机器看起来是超线程的)。
因此,如果您在单个 process/single 线程中的部分代码中执行 numpy/scipy 操作,则最好设置更大的 n
,但对于多处理部分,设置更大的池和单个或小的 n
可能会更好。不幸的是,如果您通过环境标志传递标志,则只能在脚本开头设置一次。如果你想动态设置它,我在某处的 numpy 问题讨论中看到你应该使用 threadpoolctl(如果我能再次找到它,我会添加一个 link)。
我有一段使用库 numpy, scipy, sklearn, matplotlib
的大型代码。我需要限制 CPU 的使用以阻止它消耗我的计算集群中的所有可用处理能力。在 this answer 之后,我实现了以下代码块,该代码块在脚本为 运行:
import os
parallel_procs = "4"
os.environ["OMP_NUM_THREADS"] = parallel_procs
os.environ["MKL_NUM_THREADS"] = parallel_procs
os.environ["OPENBLAS_NUM_THREADS"] = parallel_procs
os.environ["VECLIB_MAXIMUM_THREADS"] = parallel_procs
os.environ["NUMEXPR_NUM_THREADS"] = parallel_procs
我的理解是这应该将使用的核心数限制为 4,但显然这并没有发生。这是 htop
为我的用户和脚本显示的内容:
有 16 个进程,其中 4 个 CPU 的百分比显示在 100% 以上。这是 lscpu
:
CPU(s): 48
On-line CPU(s) list: 0-47
Thread(s) per core: 2
Core(s) per socket: 12
Socket(s): 2
我还在我的代码中使用 multiprocessing
库。我使用 multiprocessing.Pool(processes=4)
设置了相同数量的进程。如果没有上面显示的代码块,脚本坚持使用尽可能多的内核,显然完全忽略了 multiprocessing
。
我的问题是:当我使用上面的代码时,我限制了什么?我应该如何解释 htop
输出?
(作为评论可能更好,如果出现更好的答案,请随时删除它,因为它基于我使用库的经验。)
我在多处理部分代码时遇到了类似的问题。如果您使用 BLAS 或 MKL 编译库(或者如果您从中提取它们的 conda repo 还包含 BLAS/MKL 库),以加速某些计算。
当 运行 您的脚本在单个进程中时,这很好,因为它会产生线程数达到 OPENBLAS_NUM_THREADS
或 MKL_NUM_THREADS
指定的数量(取决于您是否有BLAS 库或 MKL 库 - 您可以使用 numpy.__config__.show()
) 来识别哪个在这种情况下,设置 n=1
(before importing numpy & scipy)或一些小数字以确保您没有超额订阅是有意义的:
n = '1'
os.environ["OMP_NUM_THREADS"] = n
os.environ["MKL_NUM_THREADS"] = n
如果设置multiprocessing.Pool(processes=4)
,它将使用4*n
个进程(每个进程中有n
个线程)。在您的情况下,您似乎有一个包含 4 个进程的池,每个进程启动 4 个线程,因此有 16 个 python 个进程。
htop
输出给出
因此,如果您在单个 process/single 线程中的部分代码中执行 numpy/scipy 操作,则最好设置更大的 n
,但对于多处理部分,设置更大的池和单个或小的 n
可能会更好。不幸的是,如果您通过环境标志传递标志,则只能在脚本开头设置一次。如果你想动态设置它,我在某处的 numpy 问题讨论中看到你应该使用 threadpoolctl(如果我能再次找到它,我会添加一个 link)。