一个Python脚本莫名其妙地占用了128个CPU?

0md85ypi  于 2023-01-29  发布在  Python
关注(0)|答案(1)|浏览(195)

我在AWS上遇到了一个非常奇怪的错误,一个基本的python脚本,没有多处理,不知何故使用了64个核心的100%,(我认为这是不可能的,因为GIL?)

    • 目标:**运行计算密集型的python代码。代码是并行的for循环,其中每个迭代都是独立的。我有两个版本的代码,一个是没有multiprocessing的基本版本,另一个使用multiprocessing模块。
    • 问题:**虚拟机是AWS上的c6i.32xlarge机器,具有64个内核/128个线程。
  • 在我的个人计算机上,使用6核处理器的并行代码大约快了6倍。在AWS机器上使用多个处理器处理相同的代码 * 会使运行速度变慢。*
    • 无法解释的部分:**
  • 我试图通过使用&设置基本脚本的多个副本来解决这个问题,但这也不起作用。运行n个副本会导致它们都慢1/n倍。令人费解的是,python脚本 * 的单个示例会使用机器 * 的所有内核。Unix命令TOP指示使用了6400%的CPU(也就是所有的),AWS的CPU使用监控确认了机器100%的使用率。我不认为这是可能的GIL。
    • 部分解决方案?**指定处理器在一定程度上解决了问题:
  • 运行命令taskset --cpu-list i my_python_script.py & for i from 1 to n,它们确实是并行运行的,并且时间与n无关(对于小n)。AWS监视器上的预期CPU使用率统计数据是 * 您所期望的 *。使用一个处理器时的速度与脚本运行并占用计算机所有内核时的速度相同。
    • 注意:**1个处理器上的运行时相同这一事实表明它实际上一直在1个内核上运行,而其他内核不知何故被错误地使用了。

问题:

为什么我的基本python脚本占用了AWS机器的所有64个内核,而速度却没有任何提高?这个错误是怎么发生的?我怎样才能让它在不使用这个奇怪的taskset --cpu-list work的情况下简单地运行多处理呢?
我在谷歌云平台上也遇到了同样的问题。
基本脚本非常简单:

from my_module import my_np_and_scipy_function
from my_other_module import input_function

if __name__ == "__main__":
    output = []
    for i in range(0, num_iter):
        result = my_np_and_scipy_function(kwds, param = input_function)
        output.extend(result)

对于multiprocessing,它是:

from my_module import my_np_and_scipy_function

if __name__ == "__main__":

    pool = multiprocessing.Pool(cpu_count)
    for i in range(0, num_iter):
        result = pool.apply_async(my_np_and_scipy_function,kwds={"param":input_function,...},
        )
        results.append(result)

    output = []
    for x in results:
        output.extend(x.get())

问题似乎与np.linalg.eigeigshscipy.sparse.linalg.eigsh有关,对于不涉及这些功能的脚本,AWS盒子上的一切都按预期工作。
我找到的解决此问题的最基本脚本是:

import numpy as np
for i in range(0, num_iter):
    x=np.linalg.eig(np.random.rand(1000,1000))
  • 注意:* 一个只运行np.random.rand(1000,1000)的循环没有问题,它具体是np.linalg.eig,它也 * 具体 * 在AWS或GCP上的虚拟云计算机上,在我的个人笔记本电脑上,一切都按预期工作。

在线程Limit number of threads in numpy之后,通过将以下代码行放在脚本的顶部,可以正常工作:

import os

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

但我不明白到底是怎么回事。

syqv5f0l

syqv5f0l1#

Numpy在一些随机函数中使用多处理。所以这是可能的。你可以看到这里https://github.com/numpy/numpy/search?q=multiprocessing

相关问题