含np.linalg.eig的Python脚本占满CPU却不提速的问题排查
核心占用异常问题:Python特征值计算脚本占用全CPU但不提速
注意:该问题仅与np.linalg.eig、eigsh和scipy.sparse.linalg.eigsh相关,不涉及这些函数的脚本在AWS服务器上运行完全正常。
最基础的问题复现脚本:
import numpy as np for i in range(0, num_iter): x=np.linalg.eig(np.random.rand(1000,1000))
我在AWS c6i系列虚拟机上遇到了一个诡异问题:一段计算特征值的基础Python脚本会占用100%的CPU核心,但运行速度完全没有提升。
目标
运行计算密集型Python代码,代码为并行for循环结构,每个迭代相互独立。我准备了两个版本的代码:一个未使用multiprocessing的基础版本,一个使用multiprocessing模块的并行版本。
问题详情
- 在个人电脑上,用6核运行并行化代码时,速度能提升约6倍;但在AWS服务器上,用超过1核运行相同代码,运行时间反而变长。
费解之处
- 尝试用
&启动多个基础脚本副本也无效:运行n个副本时,每个副本的速度都会变慢1/n倍。更奇怪的是,单个Python脚本实例会占用服务器的全部核心——Unix的TOP命令和AWS CPU监控都显示机器CPU使用率达100%。考虑到GIL的存在,完全无法理解这种情况。
临时缓解方案
指定处理器绑定后问题有所改善:
- 执行命令
taskset --cpu-list i my_python_script.py &(i从1到n),脚本可以正常并行运行,且运行时间与n(n较小时)无关,AWS监控的CPU使用率也符合预期。另外,单处理器运行时的速度和脚本占用全部核心时的速度完全相同。
注意:单处理器运行速度不变这一事实说明,脚本实际上始终只在1个核心上运行,其他核心是被错误占用的。
核心问题
- 为什么基础Python脚本会占用AWS服务器的全部核心却不提速?
- 这种错误的原因是什么?
- 如何不用
taskset --cpu-list这类临时方法,直接用multiprocessing正常运行代码?
另外,我在谷歌云平台上也遇到了完全相同的问题。
基础版本脚本
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 import multiprocessing from multiprocessing import cpu_count if __name__ == "__main__": pool = multiprocessing.Pool(cpu_count()) results = [] 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())
内容的提问来源于stack exchange,提问作者Eric Naslund
相关产品推荐
相关产品推荐

