Scipy lsim/lsim2性能优化:单核心低资源下高效运行需求
问题:单核心/低资源环境下高效运行scipy.signal.lsim
我在Python脚本中使用scipy的lsim函数进行系统模型仿真,目前遇到的问题是lsim会在多核心上生成大量子进程,导致CPU负载过高,这一点可从下方性能分析日志中体现。我在多人共享的处理机上运行脚本,改用lsim2不会生成子进程,但运行速度慢到难以接受。请问如何在单核心/少资源的情况下快速运行lsim?
性能分析日志片段
ncalls tottime percall cumtime percall filename:lineno(function) 3740 25.422 0.007 51.062 0.014 /grid/common/pkgs/python/v3.7.2/lib/python3.7/site-packages/scipy/signal/ltisys.py:1870(lsim) 26753891 21.519 0.000 21.519 0.000 {built-in method numpy.dot} 12 0.001 0.000 21.450 1.788 /grid/common/pkgs/python/v3.7.2/lib/python3.7/subprocess.py:431(run) 12 0.000 0.000 21.265 1.772 /grid/common/pkgs/python/v3.7.2/lib/python3.7/subprocess.py:895(communicate) 24 0.000 0.000 21.265 0.886 /grid/common/pkgs/python/v3.7.2/lib/python3.7/subprocess.py:985(wait) 24 0.000 0.000 21.265 0.886 /grid/common/pkgs/python/v3.7.2/lib/python3.7/subprocess.py:1592(_wait) 12 0.000 0.000 21.264 1.772 /grid/common/pkgs/python/v3.7.2/lib/python3.7/subprocess.py:1579(_try_wait)
解决方案
强制numpy使用单核心:从日志看
numpy.dot占用大量时间,numpy默认会启用多线程加速,这是高CPU负载的核心原因之一。在导入numpy和scipy前设置环境变量限制线程数:import os # 限制各类线性代数库的线程数为1 os.environ["OMP_NUM_THREADS"] = "1" os.environ["OPENBLAS_NUM_THREADS"] = "1" os.environ["MKL_NUM_THREADS"] = "1" os.environ["VECLIB_MAXIMUM_THREADS"] = "1" os.environ["NUMEXPR_NUM_THREADS"] = "1" # 之后再导入scipy和numpy import numpy as np from scipy.signal import lsim优化lsim调用方式:日志显示
lsim被调用了3740次,频繁的函数调用会增加开销。如果是循环调用处理多个仿真任务,建议将输入信号批量处理,比如把多个输入合并为二维数组,一次性传入lsim,减少调用次数和子进程创建频率。升级scipy版本:你当前使用的scipy版本适配Python3.7,属于较旧版本。新版本的scipy(1.7+)对
lsim的实现做了优化,可能减少了不必要的子进程创建,同时提升了单核心下的运行效率。手动实现核心仿真逻辑:如果你的系统是简单的线性时不变系统,可以基于状态空间模型的递推公式自行实现仿真逻辑,完全避免
lsim的额外开销和子进程问题。例如:def custom_lsim(A, B, C, D, u, t): x = np.zeros(A.shape[0]) y = [] dt = t[1] - t[0] for i in range(len(t)): x = x + dt * (A @ x + B @ u[i]) y.append(C @ x + D @ u[i]) return np.array(y)注意需根据你的系统模型调整公式,适合固定步长的仿真场景。
内容的提问来源于stack exchange,提问作者Daiz
相关产品推荐
相关产品推荐

